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

使用类作为派生约束-C#泛型有什么意义,c#,generics,C#,Generics,同样地 public void AddEmployee (Employee Employee) { // Code here } 公共类通用列表,其中T:Employee 及 公共类泛型列表 我看不出两者有什么区别。我知道当有接口作为派生约束时 public class GenericList<Employee> 公共类泛型列表,其中T:IComparable,IConvertible 但若使用了子类(如上面的employee中所示),那个对我来说并没有意义。我是不是遗

同样地

public void AddEmployee (Employee Employee)
{
 // Code here
}
公共类通用列表,其中T:Employee

公共类泛型列表
我看不出两者有什么区别。我知道当有接口作为派生约束时

public class GenericList<Employee> 
公共类泛型列表,其中T:IComparable,IConvertible

但若使用了子类(如上面的employee中所示),那个对我来说并没有意义。我是不是遗漏了什么?请解释

区别在于
列表
可以包含
Employee
或其子类的任何实例,而
列表中的T:Employee
可能更具限制性

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

例如,给定

public class GenericList<T> where T : IComparable, IConvertible 
列表
只能容纳经理,而不能容纳
Employee
基类或
Employee
的某些其他子类的实例


相比之下,您可以将
Employee
Manager
实例放入
列表中,区别在于
List
可以保存
Employee
的任何实例或其子类之一,而
列表中的T:Employee
可能更具限制性

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

例如,给定

public class GenericList<T> where T : IComparable, IConvertible 
列表
只能容纳经理,而不能容纳
Employee
基类或
Employee
的某些其他子类的实例

相反,您可以将
Employee
Manager
实例放入
关于类的列表中
这个问题与以下问题有关:非泛型
ArrayList
和泛型
列表
之间有什么区别。由于ArrayList接受任何类型的数据(都是来自基类
对象的数据),因此很容易将数据导出

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

在您的示例中,情况也是如此。假设您有一个manager类:

public class Manager : Employee
{
}
您可以创建以下列表:

public class Manager : Employee {}
这两个列表都接受
Manager
类型的实例。但只有
myList1
也接受
Employee
类型的实例。如果要从
myList1
检索经理,可能需要强制转换(性能降级)。
myList2
仅限于接受经理(和衍生产品)

简言之:
MyList
可用于任何员工衍生工具,并且不像
MyList
那样具有限制性
MyList
可以限制为任何类型,只要它是从
Employee
派生的

如果您不打算为经理编制一份专门的清单,那么在这种情况下,将不会有任何区别

关于方法 两个方法示例都有点相同。让我们使用其他示例来演示其用法:

MyList myList1 = ...;
MyList<Manager> myList2 = ...;
另一个例子:

DoSomething1(123); // <-- Will box the int.
DoSomething2(123); // <-- Will NOT box the int.
在您的情况下,当您只使用引用类型而不是返回类型的输入参数时,不会有太大的区别(关注性能)。

关于类 这个问题与以下问题有关:非泛型
ArrayList
和泛型
列表
之间的区别是什么。由于ArrayList接受任何类型的数据(所有数据都是来自基类
对象的数据),因此很容易将数据导出

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

在您的示例中,情况也是如此。假设您有一个manager类:

public class Manager : Employee
{
}
您可以创建以下列表:

public class Manager : Employee {}
这两个列表都接受
Manager
类型的实例。但只有
myList1
也接受
Employee
类型的实例。如果要从
myList1
检索经理,可能需要强制转换(性能降级)。
myList2
仅限于接受经理(和衍生产品)

简言之:
MyList
可用于任何员工衍生工具,并且不像
MyList
那样具有限制性
MyList
可以限制为任何类型,只要它是从
Employee
派生的

如果您不打算为经理编制一份专门的清单,那么在这种情况下,将不会有任何区别

关于方法 两个方法示例都有点相同。让我们使用其他示例来演示其用法:

MyList myList1 = ...;
MyList<Manager> myList2 = ...;
另一个例子:

DoSomething1(123); // <-- Will box the int.
DoSomething2(123); // <-- Will NOT box the int.

在您的情况下,当您只使用引用类型而不是返回类型的输入参数时,这不会有太大的区别(关注性能).

列表和t:Employee所在的列表不一样吗?两者都可以包含Employee的任何子类。您能进一步澄清吗?@as1-您不明白哪一位?如果
t:Employee所在的
列表可能无法包含Employee的任何子类,如果
t
是比
Employee
(例如示例中的
Manager
类)。在这种情况下,它只能包含
T
类型的子类,而不能包含任何
Employee
。因此,如果我正确获得它,使用实现的人可以将其限制为派生类型,但如果他们使用List(用于列表实现)它本质上是相同的,对吗?@as1-是的,如果您指定
Employee
作为泛型类型
T
,那么它将是相同的,但如果您使用
Tint 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.