2012-04-09 37 views
6

我有一個這樣的接口:如何在C#中的界面返回類型T?

public interface IUser{ 
    //some properties here 

    T ToDerived(User u); 
} 

我是新來的界面開發,所以這裏就是我試圖完成。我將有一個基類

public class User 

不會實現上述接口。然後,我將在SalesUser類派生類

SalesUser : User, IUser 
{ 
    //no properties needed because they exist in the User class 

    SalesUser ToDerived(User u) 
    { 
     //code for converting a base User to a derived SalesUser 
    } 
} 

我想編寫功能ToDerived(用戶U),但在界面上,我不知道如何定義這個作爲ToDerived方法聲明我現在在界面中沒有編譯。

我希望這是有道理的。

+1

[Here](http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser。aspx)是一個鏈接到Eric的博客,這與這個問題有關。它包括一個看起來很像下面答案的例子,也包括使用這種設計機制的缺陷。 – Servy 2012-04-09 19:35:34

回答

14
public interface IUser<T> where T : User 
{ 
    //some properties here 

    T ToDerived(User u); 
} 

SalesUser : User, IUser<SalesUser> 
{ 
    //no properties needed because they exist in the User class 

    SalesUser ToDerived(User u) 
    { 
     //code for converting a base User to a derived SalesUser 
    } 
} 

不知道這是你想要的,但我增加了接口的泛型類型約束,以確保泛型類型爲User或者從它繼承。

+0

打我,但我會添加'在哪裏T:用戶'。 – 2012-04-09 18:57:29

+0

@JimSchubert - 我認爲它,並加入了你的評論;) – Oded 2012-04-09 18:57:52

+0

你打我兩次:( – 2012-04-09 18:58:29

0

記住一個接口定義一個類及其成員而不提供任何實現,你可以創建一個接口,但接口必須有實現類。

+0

這是如何回答這個問題的? – Oded 2012-04-09 19:12:55

+0

我想在SalesUser類中編寫ToDerived(User u)的函數,但在接口中,我不知道如何將此定義爲ToDerived方法聲明,我不知道我是否錯了。 – 2012-04-09 19:26:02

3

Oded的答案解決了編譯問題,允許您定義滿足接口的ToDerived方法。但是,正如我在評論中所述,我不確定這是最好的實施。

我遇到的主要問題是像這樣的轉換方法通常需要在靜態上下文中。您沒有SalesUser的實例;你需要一個,並有一個用戶,所以你在靜態上下文中調用方法(SalesUser.ToDerived(myUser)),你得到一個SalesUser(該方法將更適當地命名爲FromUser()或類似的)。您在界面中指定的方法要求您已經有SalesUser以將用戶轉換爲SalesUser。唯一可以想到的情況是,您真的需要一個預先存在的SalesUser用於「部分克隆」;您正在使用傳入和傳出調用該方法的SalesUser的用戶信息創建一個新的SalesUser實例。在所有其他情況下,您不需要SalesUser(轉換,如上所述應該是靜態的),或者您不需要用戶(一種「克隆」或「深層複製」方法,用於生成一個新實例與您調用該方法的實例相同的數據)。

此外,類的消費者必須知道他們必須調用ToDerived()才能執行從用戶到SalesUser的轉換。通常情況下,C#程序員所期望的顯式或隱式轉換爲可用:

public class SalesUser 
{ 

    public static explicit operator (User user) 
    { 
     //perform conversion of User to SalesUser 
    } 

} 

//the above operator permits the following: 
mySalesUser = (SalesUser)myUser; 

...或者,沒有一個轉換操作符,人們會期望能夠使用用戶構建一個SalesUser:

public class SalesUser:IUser 
{ 
    public SalesUser(User user) 
    { 
     //initialize this instance using the User object 
    } 
} 

//the above allows you to do this: 
mySalesUser = new SalesUser(myUser); 

//and it also allows the definition of a method like this, 
//which requires the generic to be an IUser and also requires a constructor with a User 
public void DoSomethingWithIUser<T>(User myUser) where T:IUser, new(User) 
{ 
    //...which would allow you to perform the "conversion" by creating a T: 
    var myT = new T(myUser); 
} 

現在,靜態成員不滿足接口定義,並且接口無法定義靜態成員或構造函數簽名。這告訴我,IUser接口不應該嘗試定義轉換方法;相反,需要某種IUser的方法可以簡單地指定該方法,並且用戶可以根據需要提供實現,而實現不需要知道它可以轉換爲自己。

+0

你說得對,Oded確實解決了這個問題,並以我正在尋找的確切方式回答了我的問題。然而,我喜歡你對此的解釋,爲什麼我不應該使用這種設計模式,因爲這種特定的方法通常是一種靜態方法(我同意)。 但是,當我嘗試構建示例時,請記住我需要SalesUser類來繼承基類User類。 public class SalesUser:User,IUser 因此,當我嘗試這樣做時,您的顯式方法不起作用。 「不允許用戶自定義轉換到基類或從基類轉換。」 – jaressloo 2012-04-09 20:54:54

+0

基於構造函數的「轉換」應該仍然有效。 – KeithS 2012-04-09 21:23:15

+0

是的,基於構造函數的版本是現在選擇採用的路線。將試圖找出另一種方式,雖然允許從基本用戶顯式轉換派生SalesUser。謝謝你的幫助。 – jaressloo 2012-04-10 15:34:49