interface IFly<T>
{
T GetMark();
}
public class Bird : IFly<string>
{
public string GetMark()
{
return "Bird";
}
}
public class Plane : IFly<int>
{
public int GetMark()
{
return 123;
}
}
class Program
{
static void Main()
{
IFly<string> bird = new Bird();
IFly<int> plane = new Plane();
Console.WriteLine(bird.GetMark());
Console.WriteLine(plane.GetMark());
Console.ReadKey();
}
}
我想替换这个
IFly<string> bird = new Bird();
IFly<int> plane = new Plane();
有这样的事情:
var fly = new List<IFly<T>>
有什么建议吗?
答案 0 :(得分:3)
这可能有效:
public interface IFlyRoot { }
interface IFly<T> : IFlyRoot
{
T GetMark();
}
然后你可以制作List<IFlyRoot>
。
答案 1 :(得分:2)
一般情况下,@ Steve的答案是正确的。但是,根据您的需要,您可以尝试使用类型差异,但它不支持值类型(int
不起作用)。
注意接口定义中的out
:
interface IFly<out T>
{
T GetMark();
}
然后你可以写:
var list = new List<IFly<object>>();
list.Add(bird);
但它不适用于Plane
,其中T
是值类型(此处为:int
)。此解决方案可能不适合您的确切需求。
要更深入地了解为什么方差不适用于值类型,请参阅Jon Skeet或Eric Lippert的答案。简而言之,这是因为应该保留引用标识,但是不能使用值类型。值类型总是先装箱,丢失该标识。这就是它不能自动运行的原因。这并不是一个干净利落的方式。您可以尝试的一件事是让Plane
类明确地实现IFly<object>
:
public class Plane : IFly<int>, IFly<object>
{
public int GetMark()
{
return 123;
}
object IFly<object>.GetMark()
{
return GetMark();
}
}
并添加到列表中:
list.Add(new Plane());
答案 2 :(得分:0)
由于CLR将IFly和IFly视为不同的类型,因此您需要在两者之间建立更直接的关系,在这种情况下,通过实现IFly接口的非泛型版本。然后,只要集合实现此公共接口,集合就会存储对象,例如:
class Program
{
static void Main()
{
var flyingThings = new ThingsThatFlyCollection();
var bird = new Bird();
var bird2 = new Bird();
var plane = new Plane();
flyingThings.Add(bird);
flyingThings.Add(bird2);
flyingThings.Add(plane);
Console.WriteLine(flyingThings.GetItemWithCast<string>(0).GetMark());
Console.WriteLine(flyingThings.GetItemWithCast<string>(1).GetMark());
Console.WriteLine(flyingThings.GetItemWithCast<int>(2).GetMark());
foreach (var item in flyingThings.GetItemsWithCast<int>())
{
Console.WriteLine(item.GetMark());
}
foreach (var item in flyingThings.GetItemsWithCast<string>())
{
Console.WriteLine(item.GetMark());
}
foreach (var item in flyingThings.GetItemsByType<Bird>())
{
Console.WriteLine(item.GetMark());
}
Console.ReadKey();
}
}
public interface IFly
{
object GetMark();
}
public interface IFly<TMark> : IFly
{
new TMark GetMark();
}
class Plane : IFly<int>
{
public int GetMark() { return 123; }
object IFly.GetMark() { return this.GetMark(); }
}
class Bird : IFly<string>
{
public string GetMark() { return "Bird"; }
object IFly.GetMark() { return this.GetMark(); }
}
class ThingsThatFlyCollection : Collection<IFly>
{
public IFly<TMark> GetItemWithCast<TMark>(int index)
{
var f = this[index] as IFly<TMark>;
if (f == null) { throw new InvalidCastException(); }
return f;
}
public IEnumerable<IFly<TMark>> GetItemsWithCast<TMark>()
{
var items = this.Where(p => p is IFly<TMark>).Cast<IFly<TMark>>();
return items;
}
public IEnumerable<TFlyer> GetItemsByType<TFlyer>() where TFlyer : IFly
{
var items = this.Where(p => p.GetType() == typeof(TFlyer)).Cast<TFlyer>();
return items;
}
}
请记住,根据交易量的不同,向上转换可能会产生一些性能影响,但对于大多数情况来说可能会忽略不计。