49

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

这编译:

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 可以按照我的意愿做出反应。我会接受分享更多信息的答案。

4

3 回答 3

59

首先,尝试对泛型参数设置两种类型约束的代码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类本身的后继类型,并且它必须同时实现IContractorANDIComparable接口。

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

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

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

如果您的类 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;
}
于 2013-07-23T16:22:17.717 回答
15

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

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

我更喜欢单独的版本,真的,因为他们不能用Supplierand来调用它EmployeeDeparment(反之亦然)

于 2013-07-23T15:22:28.823 回答
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
}
于 2013-07-23T15:30:11.917 回答