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
但是如果使用了子类(如上面的员工那样),那对我来说没有意义。我在这里错过了什么吗?请解释
答案 0 :(得分:6)
区别在于List<Employee>
可以容纳Employee
或其子类之一的任何实例,而List<T> where T : Employee
可能更具限制性。
这是因为泛型类型T
可以是Employee
的任何子类,在这种情况下,列表只能包含T
的子类的实例,而不能包含任何{{1}实例。
例如,给定
Employee
public class Manager : Employee
{
}
只能包含管理员,而不是List<Manager>
基类的实例,或Employee
的其他子类。
相反,您可以将Employee
和Employee
个实例放入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 = ...;
myList1
和myList2
willa都接受Employee
个实例和Manager
个实例。到目前为止没有区别。 (这与比较ArrayList
和List<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}}
在您的情况下,当您仅使用作为引用类型而非返回类型的输入参数时,它不会产生太大的影响(关注性能)。