具有多个类的泛型

Posted

技术标签:

【中文标题】具有多个类的泛型【英文标题】:Generic with multiple classes 【发布时间】:2013-07-23 15:19:17 【问题描述】:

我正在尝试创建这种通用方法来简化事情,但我想我搞砸了!你能帮忙解决我的问题吗?

这样编译:

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);

消息:类型 Supplier 不能用作泛型类型或方法 ConcatenateText(MyEntity myEntity) 中的类型参数 T1。没有从供应商到员工的隐式引用转换

这可以吗?我究竟做错了什么?可以改进吗?

编辑:

而 MyEntity 只是另一个类,以便在这个通用方法中处理它!它与类型 T 无关。它只是一个参数。但很明显,我不能这样做,使用 2 种这样的类型。我认为我可以分配一个或另一个,独立于我的初始化的 CLR 可以按照我的意愿做出反应。我会接受分享更多信息的答案。

【问题讨论】:

【参考方案1】:

首先,尝试对泛型参数T1 设置两种类型约束的代码无法编译

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

出现以下错误:

已经为类型参数“T1”指定了约束子句。类型参数的所有约束都必须在单个 where 子句中指定。

正如 MSDN 文章所述,您只能对每个通用参数使用一个 where 约束(请参阅 http://msdn.microsoft.com/en-us/library/bb384067.aspx)。

“有多个类型参数,每个类型参数使用一个where子句...”

您也不能将多个类名放入一个“where”约束中。只有一个类名和几个接口。

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

请记住,此约束规定您作为泛型参数T1 提供的实际类型必须是Supplier 类或Supplier 类本身的后继类型,并且它必须同时实现IContractor 和@ 987654330@接口。

一旦你的方法接受MyEntity 对象并且你没有指定它与EmployeeSupplier 类的关系,我无法猜测这个MyEntity 类如何知道Employee 和@987654336 @classes 以及这种关系如何帮助你。

我唯一能建议的是创建一个接口或一个基类,并从中继承你的两个类。这是我看到创建泛型方法的唯一充分理由。它可能看起来像这样:

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
    
        getreturn "Supplier-Mufflier";
    


public class Employee : IContractor

    string IContractor.Name
    
        getreturn "Employee-Merloyee";
    


public interface IContractor

    string Name
    
        get;
    

如果您的类 Supplier 和 Employee 没有一些重要的共同点足以创建它们可以实现的通用接口,那么您不应该创建一个通用方法来处理它们。

为每个此类类型创建一个重载方法。

假设您有两个类: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;

【讨论】:

哎呀,当我写我的答案时,另外两个出现并说几乎相同 很好的答案,但如果我没记错的话,你不能在一个班级上重载多个班级。所以在这个例子中接口和泛型是一个不错的选择。 @TarıkÖzgünGüner 不要混淆过载和覆盖。【参考方案2】:

您要么需要制作单独的版本:

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 调用它(反之亦然)

【讨论】:

单独的版本不起作用。您已经定义了两个具有相同名称和相同参数的方法。不幸的是,更改返回类型并不能使其可重载。【参考方案3】:

在这种情况下你真的不应该使用泛型。 只有两个选项。

所以:

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

【讨论】:

以上是关于具有多个类的泛型的主要内容,如果未能解决你的问题,请参考以下文章

具有多个结构的泛型和依赖倒置

泛型类的基本使用

具有通用参数和抽象类的泛型

方法中的泛型--同一方法中使用多个泛型 子类

java中的泛型方法

如何根据T创建不同行为的泛型方法?