2013-07-23 53 views
21

我想創建這個通用的方法來簡化的東西,但我想我搞砸了!你能幫我解決問題嗎?通用與多個類

這將編譯:

private string ConcatenateText<T1, T2>(MyEntity myEntity) 
    where T1 : Supplier, new() 
    where T1 : Employee, new() 
    where T2 : SupplierDepartment, new() 
    where T2 : EmployeeDepartment, new() 
{ 
    T1 p = new T1(); 
    T2 r = new T2(); 
    //Code here for myEntity treatment 
    return mystring; 
} 

雖然這並不編譯:

protected void mybutton1_Click(object sender, EventArgs e) 
{ 
    string mystring = ConcatenaText<Supplier, SupplierDepartment>(myEntity); 
} 

//This does not compile 
protected void mybutton2_Click(object sender, EventArgs e) 
{ 
    string mystring = ConcatenaText<Employee, EmployeeDepartment>(myEntity); 
} 

消息:該類型供應商不能用作在通用類型或方法ConcatenateText類型參數T1(myEntity所myEntity所)。沒有從供應商到員工的隱含參考轉換

可以這樣做嗎?我究竟做錯了什麼?可以改進嗎?

編輯:

而且myEntity所是另一個類,以處理它這個泛型方法裏面!它與類型T無關。它只是一個參數。但很明顯,我不能這樣做,使用2種類型。我認爲我可以分配一個或另一個,獨立於我的初始化的CLR可以按我的意願做出反應。我會接受那些分享更多關於它的信息的答案。

回答

24

首先,你的代碼,試圖在設置兩個類型約束通用參數T1不編譯

where T1 : Supplier, new() 
where T1 : Employee, new() 

,出現以下錯誤:

A constraint clause has already been specified for type parameter 'T1'. All of the constraints for a type parameter must be specified in a single where clause.

由於MSDN文章指出,你可以在每個泛型參數只使用一個where約束(見http://msdn.microsoft.com/en-us/library/bb384067.aspx)。

"With multiple type parameters, use one where clause for each type parameter..."

您也不能將多個類名放入一個'where'約束中。只有一個類名和幾個接口。

where T1 : Supplier, IContractor, IComparable, new() 

請記住,這個約束決定了您提供的泛型參數T1實際的類型必須爲供應商類或供應商類本身的繼承者,它必須實現兩個IContractorIComparable接口。

只要您的方法接受MyEntity對象並且您沒有指定它與Employee和Supplier類的關係,我就無法猜測這個MyEntity類如何知道Employee和Supplier類以及這個關係如何幫助您。

我可以建議的唯一方法是創建一個接口或一個基類,並從中繼承兩個類。這是我看到創建通用方法的唯一理由。它看起來是這樣的:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Method1<Employee>(); 
     Method1<Supplier>(); 
    } 

    private static void Method1<T1>() 
     where T1 : IContractor, new() 
    { 

    } 
} 

public class Supplier : IContractor 
{ 
    string IContractor.Name 
    { 
     get{return "Supplier-Mufflier";} 
    } 
} 

public class Employee : IContractor 
{ 
    string IContractor.Name 
    { 
     get{return "Employee-Merloyee";} 
    } 
} 

public interface IContractor 
{ 
    string Name 
    { 
     get; 
    } 
} 

如果你的類供應商和員工沒有共同之處是足以建立一個通用的接口,他們可以實現,那麼你不應該做一個通用的方法處理他們很重要。

爲每種類型創建一個重載方法。

想象一下你有兩類:WifeWine。兩者都具有Age的屬性以及相同類型的屬性。但是別想爲這些類創建一個通用接口IAged。類的本質和Age的含義是如此不同以至於不應該將它們統一起來。儘管如此,一些常見的邏輯可能完全爲您服務例如:

private double AgeQualify(Wife someWife) 
{ 
    return 1/(someWife.Age * someWife.Beachness); 
} 

private double AgeQualify(Wine someWine) 
{ 
    return someWine.Age/someWine.Sugar; 
} 
+0

哎呀,當我在寫我的回答另外兩個出現,並說幾乎相同 –

+0

偉大的答案,但如果我沒記錯,你不能在一個類重載多類。所以在這個例子中Interface和generic是一個很好的選擇。 –

+1

@TarıkÖzgünGüner不要混淆過載和覆蓋。 –

8

您也需要做出不同的版本:

private string ConcatenateText<T1, T2>(MyEntity myEntity) 
    where T1 : Supplier, new() 
    where T2 : SupplierDepartment, new() 
{ 
    T1 p = new T1(); 
    T2 r = new T2(); 
    return mystring; 
} 

private string ConcatenateText<T1, T2>(MyEntity myEntity) 
    where T1 : Employee, new() 
    where T2 : EmployeeDepartment, new() 
{ 
    T1 p = new T1(); 
    T2 r = new T2(); 
    return mystring; 
} 

或需要讓他們共享一個基礎類:

private string ConcatenateText<T1, T2>(MyEntity myEntity) 
    where T1 : EmployeeSuplierBase, new() 
    where T2 : EmployeeSupplierDeparmentBase, new() 
{ 
    T1 p = new T1(); 
    T2 r = new T2(); 
    return mystring; 
} 

我寧願單獨的版本,真的,因爲他們他們不能用SupplierEmployeeDeparment(或反之亦然)調用它

2

你真的不應該在這種情況下使用泛型。 只有兩個選項。

所以:

string ConcatenateText(Supplier Entity) { ...code...} 
string ConcatenateText(Employee Entity) { ...code...} 

你可以做的是一個基類集中所有常用的方法統一兩者。

說,如果供應商和員工都有Name

class BaseClass 
{ 
    public string Name {get; set;} 
} 

class Employee : BaseClass 
{ 
    //emplyee stuff except name and other things already in base 
} 

class Supplier : BaseClass 
{ 
    //supplier stuff except name and other things already in base 
} 

然後,該方法需要BaseClass

private string ConcatenateText(BaseClass Entity) 
{ 
    //code 
}