setting/determining List<interface> 或 List<abstractClass> 中具体类型的最佳实践是什么?

What is the best practice for setting/determining the concrete types in a List<interface> or List<abstractClass>?

如果我有:

List<iCanSpeak>List<Animal>

其中许多类型实现接口 iCanSpeak 或使用抽象 class Animal 作为基础 class.

determining/setting 我实际列表中的具体类型的最佳做法是什么?

我知道 C# 提供 .TypeOf 并且我看到了在基础 class 或接口中使用枚举的示例,以便更容易确定,但什么是最佳实践,为什么?

可能偏离主题的跟进:

此外,TypeOf 在幕后做什么?它正在铸造吗?为什么不同混凝土 class 的属性在放入 list<abstractClass> 时不会丢失?

是否... List<AbstractClass> == List<interface>

定义的方法和属性是否相同?

您可以使用 .OfType<TSomeInterfaceOrClassOrAbstractClassOrStruct>() 扩展方法来 select 所有属于 iCanSpeak 类型或从其继承的列表成员。

在您的情况下,这可能是:MyList.OfType<ICanSpeak>()

一些参考文献:DotNetPearls and MSDN.

Does... List<AbstractClass> == List<interface>

If the defined methods and properties are the same?

没有。他们没有。由于列表是通用的 class,您不能将它们相互转换。您将需要一个 cast/convert 函数来为您执行此操作。

这可以是 .OfType<T> 过滤器,或者 .Cast<T> returns 那个类型的新 IEnumerable,或者 .Select(x => (yournewtype)x) [=62] =] yournewtypeIEnumerable。如果可能的话,我更喜欢.Cast<T>(这种方法是为了将implementation的列表转换为IInterfaceThatIsImplemented的列表),否则如果你不需要所有成员,.OfType<T>,但只有特定类型的。

示例:

var cars = new List<Car>();
var vehicles = cars.Cast<IVehicle>(); // works
var carsAndBicycles = new List<IVehicle>(); // think of some cars and bicycles in here
var otherCars = carsAndBicycles.OfType<Car>(); // works
var broken = carsAndBicycles.Cast<Car>(); // this breaks when carsAndBicycles doesnt only contain cars 
// this is what .OfType<T> is useful for.

更深入 - 我上面写的不是很准确。

(来源:Jon Skeets Edulinq Implementation/Blog

List<AbstractClass>List<interfaceThatIsImplementedInAbstractClass>是一样的

不是在 C# 类中,编译器不允许,但 CLR 允许。

如果绕过编译器的检查,它就可以工作。

(我不推荐在任何理智的代码中使用那个“hack”!)

int[] ints = new int[10];
// Fails with CS0030
IEnumerable<uint> uints = (IEnumerable<uint>) ints;
        
// Succeeds at execution time
IEnumerable<uint> uints = (IEnumerable<uint>)(object) ints;

让我们玩得更开心:

int[] ints = new int[10];
        
if (ints is IEnumerable<uint>)
{
    Console.WriteLine("This won’t be printed");
}
if (((object) ints) is IEnumerable<uint>)
{
    Console.WriteLine("This will be printed");
}