使用类作为派生约束有什么意义 - C#泛型

时间:2013-05-25 11:22:33

标签: c# generics

public void AddEmployee<T> (T employee) where T : Employee
{

  //some code here


 }

但如果我这样写的话

public void AddEmployee (Employee Employee)
{
 // Code here
}

类似地,

public class GenericList<T> where T : Employee

public class GenericList<Employee> 

我认为两者之间没有任何区别。我理解当有接口作为派生约束时,如

public class GenericList<T> where T : IComparable, IConvertible 

但是如果使用了子类(如上面的员工那样),那对我来说没有意义。我在这里错过了什么吗?请解释

2 个答案:

答案 0 :(得分:6)

区别在于List<Employee>可以容纳Employee或其子类之一的任何实例,而List<T> where T : Employee可能更具限制性。

这是因为泛型类型T可以是Employee的任何子类,在这种情况下,列表只能包含T的子类的实例,而不能包含任何{{1}实例。

例如,给定

Employee

public class Manager : Employee { } 只能包含管理员,而不是List<Manager>基类的实例,或Employee的其他子类。

相反,您可以将EmployeeEmployee个实例放入Manager

答案 1 :(得分:3)

关于班级

这个问题与以下问题相同:非通用ArrayList和通用List<T>之间有什么区别。由于ArrayList接受任何类型的数据(所有数据都来自基类object,因此很容易将数据输出。

有一个很大的缺点:当您从ArrayList中提取数据时,必须将其转换回原始数据类型。

在你的例子中,同样的事情。假设你有一个经理班:

public class Manager : Employee {}

你创建了列表:

public class MyList: List<Emplyoyee> {}
public class MyList<T>: List<T> where T : Employee {}
...
MyList myList1 = ...;
MyList<Employee> myList2 = ...;

myList1myList2 willa都接受Employee个实例和Manager个实例。到目前为止没有区别。 (这与比较ArrayListList<object>相同。)

但是现在试试这个:

MyList myList1 = ...;
MyList<Manager> myList2 = ...;

两个列表都接受Manager类型的实例。但只有myList1也接受Employee类型的实例。如果你想从myList1检索一个经理,你可能需要把它投出来(降低性能)。 myList2仅限于接受经理(和衍生品)。

简而言之:MyList可用于任何Employee-derivative,并不像MyList<T>那样受限制。只要MyList<T>派生自Employee,就可以将void DoSomething1(object value) {}; void DoSomething2<T>(T value) {}; 重新传输到任何类型。它

如果您不打算为经理人制作专门的名单,那么就不会有任何差异。

关于方法

你的方法示例都有点相同。让我们用其他一些例子说明用法:

DoSomething1

两种方法都接受任何参数。例外情况,如果您使用DoSomething2的值类型,则该值将被加框。拳击是一种表现惩罚。 DoSomething1(123); // <-- Will box the int. DoSomething2(123); // <-- Will NOT box the int. 会根据其类型进行调整。因此:

object Copy1(object value) {};
T Copy2<T>(T value) {};

另一个例子:

object

两种方法都复制了参数并将其返回(现在如何,无关紧要)。在第一个示例中,返回int copy1 = (int)Copy1(123); // <-- Will box the int, and the copy needs to be unboxed. int copy2 = Copy2(123); // <-- Will NOT box the int, and the copy does NOT need to be unboxed or casted. 。如果您想使用该副本,您必须先将其投射。也许拆箱吧。两个表现洛杉矶。在第二个Copy-method中,您始终会获得与参数相同类型的返回值。因此:

{{1}}

在您的情况下,当您仅使用作为引用类型而非返回类型的输入参数时,它不会产生太大的影响(关注性能)。

相关问题