有人可以告诉我以下
之间的区别public class CarCollection<T>:List<T> where T:Car{}
和
public class CarCollection:List<Car>{}
对我来说,他们似乎做同样的事情,创建“Car”对象的类型安全集合。
答案 0 :(得分:7)
当您需要有关泛型类型参数的一些信息时,约束很好。通过约束类型,您不仅限制了有效类型参数的集合,而且还使您能够根据该类型的公共元素做出编译时决策。
在您的具体示例中,通用约束不提供任何好处,但在其他情况下它们可以。考虑这个例子:
T foo<T>()
{
return null;
}
这个方法无法编译,因为编译器知道(当我编写方法时我也应该知道)泛型类型参数可能是一个无法设置为null
的值类型。通过添加约束,我可以编译此代码:
T foo<T>()
where T : class
{
return null;
}
我现在已经将有效的泛型类型参数集限制为只有类。由于编译器现在知道T
必须是一个类,它允许我返回null
,因为不存在无法返回null
的情况。虽然这不是一个非常有用的例子,但我相信你可以推断这有用的方法。
答案 1 :(得分:4)
如果实现将执行比较的泛型,则where子句是必需的。例如:
public class Foo<T> where T : IComparable<T>
{
public static void Bar(T blah, T bloo)
{
if(blah.CompareTo(bloo) < 0) //needs the constraint
Console.WriteLine("blee!");
}
}
这是一个具体示例,但它说明了where子句标识您的泛型类型将遵循某种类型,从而能够利用功能的概念。
答案 2 :(得分:1)
我认为第二种格式具有误导性:“Car”是一个模板参数,而不是对你可能定义的“Car”类的引用。
第一种格式允许您在模板类中的T实例上调用Car类的成员(方法和属性)。
class Car
{
public void drive() {}
}
public class CarCollection<T>:List<T> where T:Car
{
List<T> list;
void driveCars()
{
foreach (T car in list)
{
//know that T is Car
car.drive();
}
}
}
public class CarCollection<Car>:List<Car>
{
List<Car> list;
void driveCars()
{
foreach (Car car in list)
{
//compiler error: no relation between the 'Car' template parameter
//and the 'Car' class
car.drive();
}
}
}
答案 3 :(得分:0)
这都是关于展示意图的。如果类的用户知道对类型参数施加了什么约束,他们可以设计更高保真度的代码。
另外,您的代码变得更加自我记录。
答案 4 :(得分:0)
第一个例子更灵活。只要T is Car
第二个例子说它必须是一辆汽车。您无法使用CompactCar
或Truck
来使用秒。这是CompactCar
或Truck
来自Car
答案 5 :(得分:0)
最上面一个创建一个类型的Car集合或任何来自Car像SportsCar的东西。
public class SportsCar : Car
{
bool Turbo { get; set;}
}
在顶部,我可以创建一个跑车集合
var sports = new CarCollection<SportsCar>();
sports.Add(new SportsCar());
...
sports.First().Turbo = true;
在底部,我有
var cars = new CarCollection<Car>();
cars.Add(new SportsCar());
((SportsCar)cars.First()).Turbo = true;
它类似于拥有一组对象与一组字符串。 :)
答案 6 :(得分:0)
经过所有帖子后,我认为最有价值的用途之一尚未被讨论过(除非我错过了)。
您可以指定T
必须实现多个接口。假设您希望它为ISomething
,ISomethingElse
和IOneOtherThing
。您可以指定这三个特定接口。
static void DoSomething<T>(T myobj)
where T : ISomething, ISomethingElse, IOneOtherThing
{
myobj.Something();
myobj.SomethingElse();
myobj.OneOtherThing();
}
一个案例可能是您需要能够比较(IComparable)两个泛型类型并返回一个克隆(IClonable)的情况。或类似的东西。
我试图想出一种干净且可重复使用的方法,在没有此功能的情况下完成同样的事情。