具有多个类的通用

Max*_*mus 35 c# generics parameters types

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

这编译:

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;
}
Run Code Online (Sandbox Code Playgroud)

虽然这不编译:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:

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

Zve*_*niy 44

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

where T1 : Supplier, new()
where T1 : Employee, new()
Run Code Online (Sandbox Code Playgroud)

出现以下错误:

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

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

"对于多个类型参数,请为每个类型参数使用一个where子句......"

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

where T1 : Supplier, IContractor, IComparable, new()
Run Code Online (Sandbox Code Playgroud)

请记住,此约束规定您作为泛型参数提供的实际类型T1必须是Supplier类或Supplier类本身的后继,并且必须实现两个IContractorAND IComparable接口.

一旦您的方法接受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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

想象一下,你有两个课程: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;
}
Run Code Online (Sandbox Code Playgroud)


It'*_*ie. 13

您需要制作单独的版本:

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;
}
Run Code Online (Sandbox Code Playgroud)

或者需要让它们共享一个基类:

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;
}
Run Code Online (Sandbox Code Playgroud)

我宁愿单独的版本,真的,因为他们他们不能把它SupplierEmployeeDeparment(或反之亦然)