C# 具有多个类的通用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17814312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:32:38  来源:igfitidea点击:

Generic with multiple classes

c#genericstypesparameters

提问by Maximus Decimus

I'm trying to create this generic method to simplify things but I think I messed it up! Can you help with my problem?

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

This compiles:

这编译:

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

While this does not compile:

虽然这不编译:

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

Message: The type Supplier cannot be used as type parameter T1 in the generic type or method ConcatenateText(MyEntity myEntity). There is no implicit reference conversion from Supplier to Employee

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

Can this be done? What am I doing wrong? Can it be improved?

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

EDIT:

编辑:

And MyEntity is just another class in order to process it inside this generic method! It's not related to the types T. It just an argument. But it's clear that I can't do that, using 2 types like that. I thought that I could assign one or another and the CLR independently of my initialization could react as I wanted. I gonna accept the answer who share a little bit more information about it.

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

采纳答案by Zverev Evgeniy

First of all, your code that tries to set two type constraints on generic parameter T1does not compile

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

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

with the following error:

出现以下错误:

A constraint clause has already been specified for type parameter 'T1'. All of the constraints for a type parameter must be specified in a single where clause.

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

As MSDN article states you can use only one whereconstraint on each generic parameter (see http://msdn.microsoft.com/en-us/library/bb384067.aspx).

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

"With multiple type parameters, use one where clause for each type parameter..."

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

You also cannot put multiple class names into one 'where' constraint. Only one class name and several interfaces.

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

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

Keep in mind that this constraint dictates that the actual type you provide as the generic parameter T1must be a successor of the Supplierclass or Supplierclass itself AND it has to implement both IContractorAND IComparableinterfaces.

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

As soon as your method accepts a MyEntityobject and you do not specify what relation it has to Employeeand Supplierclasses, I cannot guess how this MyEntityclass knows about Employeeand Supplierclasses and how this relation helps you.

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

The only thing I can suggest is either to create an interface or a base class and inherit both of your classes from it. This is the only good reason I see for creating a generic method. It could look like this:

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

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

If your classes Supplier and Employee do not have something important in common that is enough for creating a common interface they could implement then you should not make a generic method for processing them.

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

Create an overloaded method for each of such types.

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

Imagine you have two classes: Wifeand Wine. Both have an attribute of Ageand of the same type too. But do not even think of creating a common interface IAgedfor those classes. The essence of the classes and the meaning of the Ageis so different that one should never unify them. Nevertheless some common logic might perfectly serve you. For example:

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

回答by It'sNotALie.

You either need to make separate versions:

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

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

or need to make them share a base class:

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

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

I'd prefer the separate versions, really, because with them they can't call it with Supplierand EmployeeDeparment(or vice versa)

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

回答by Daniel M?ller

You really should not use generics in that case. There are only two options.

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

So:

所以:

string ConcatenateText(Supplier Entity) { ...code...} 
string ConcatenateText(Employee Entity) { ...code...}  

What you can do is unify both with a base class concentrating all common methods.

您可以做的是将两者与一个集中所有常用方法的基类统一起来。

Say, if both supplier and employee has Name:

假设,如果供应商和员工都有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
}

And then, the method takes BaseClass:

然后,该方法需要BaseClass

private string ConcatenateText(BaseClass Entity) 
{ 
    //code
}