具有多个类的通用

时间:2013-07-23 15:19:17

标签: c# generics types parameters

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

编译:

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无关。它只是一个论点。但很明显,我不能这样做,使用两种类型。我认为我可以分配一个或另一个,CLR独立于我的初始化可以按我的意愿做出反应。我会接受那些分享更多信息的答案。

3 个答案:

答案 0 :(得分:38)

首先,尝试在泛型参数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 AND { {1}}接口。

只要您的方法接受MyEntity对象并且您没有指定它与Employee和Supplier类之间的关系,我就无法猜测此MyEntity类如何了解Employee和Supplier类以及此关系如何帮助您。

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

IComparable

如果您的类别供应商和员工没有共同的重要内容足以创建他们可以实现的通用接口,那么您不应该使用通用方法来处理它们。

为每种类型创建重载方法。

想象一下,您有两个课程: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; } } Wife。两者都具有Wine属性和相同类型的属性。但是,甚至不要考虑为这些类创建一个公共接口Age。类的本质和IAged的含义是如此不同,以至于不应该统一它们。然而,一些常见的逻辑可能完全为您服务例如:

Age

答案 1 :(得分:11)

您需要制作单独的版本:

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 :(得分:1)

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

所以:

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
}