使用类作为派生约束-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.