具有多个类的泛型
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
对象并且你没有指定它与Employee
和Supplier
类的关系,我无法猜测这个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 没有一些重要的共同点足以创建它们可以实现的通用接口,那么您不应该创建一个通用方法来处理它们。
为每个此类类型创建一个重载方法。
假设您有两个类:Wife
和 Wine
。两者都具有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;
我更喜欢单独的版本,真的,因为他们不能用Supplier
和EmployeeDeparment
调用它(反之亦然)
【讨论】:
单独的版本不起作用。您已经定义了两个具有相同名称和相同参数的方法。不幸的是,更改返回类型并不能使其可重载。【参考方案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
【讨论】:
以上是关于具有多个类的泛型的主要内容,如果未能解决你的问题,请参考以下文章