C# 多态性-我没有得到什么?
我对C#中的多态性有问题。我有一个实现接口的对象,但我不能将对象的集合表示为接口的集合。这与我对多态性的理解背道而驰。所以我想知道我哪里做错了C# 多态性-我没有得到什么?,c#,c#-4.0,polymorphism,C#,C# 4.0,Polymorphism,我对C#中的多态性有问题。我有一个实现接口的对象,但我不能将对象的集合表示为接口的集合。这与我对多态性的理解背道而驰。所以我想知道我哪里做错了 [TestFixture] class Tester { [Test] public void Polymorphism() { var list = new List<Foo> {new Foo {Name = "Item"}}; Assert.That(list, Is.Insta
[TestFixture]
class Tester
{
[Test]
public void Polymorphism()
{
var list = new List<Foo> {new Foo {Name = "Item"}};
Assert.That(list, Is.InstanceOf<IList>());
Assert.That(list[0], Is.InstanceOf<Foo>());
Assert.That(list[0], Is.InstanceOf<IBar>());
// why are the rest true but this false?
Assert.That(list, Is.InstanceOf<IList<IBar>>());
}
}
internal interface IBar
{
}
internal class Foo : IBar
{
public string Name { get; set; }
}
[TestFixture]
类测试员
{
[测试]
公共空间多态性()
{
var list=新列表{new Foo{Name=“Item”};
Assert.That(list,Is.InstanceOf());
Assert.That(列表[0],是.InstanceOf());
Assert.That(列表[0],是.InstanceOf());
//为什么其余的都是真的而这是假的?
Assert.That(list,Is.InstanceOf());
}
}
内部接口IBar
{
}
内部类Foo:IBar
{
公共字符串名称{get;set;}
}
这是一个差异问题,而不是多态性问题
如果Foo列表也是IBar的IList,那么以下内容也可以:
class Another : IBar {}
IList<IBar> list = new List<Foo>();
list.Add(new Another());
另一类:IBar{}
IList list=新列表();
添加(新的另一个());
然后我们在Foo列表中添加了另一个。这是一个错误。编译器阻止你犯错误
请注意,最近的编译器/.net版本支持通过“in”/“out”进行差异。因此,Foo列表可以作为IBar的IEnumerable。因为这保证只返回Foo(不接受它们),而且所有Foo也是IBar-因此它是安全的。我也会投入我的两分钱。如果您增加对协方差和逆变换的理解,您所遇到的问题可以更好地理解(请参阅) 我对您的代码进行了一些修改,并提出了以下有效的测试方法:
public void TestMethod1()
{
var list = new List<Foo> { new Foo { Name = "Item" } };
Assert.IsNotNull(list as IList);
Assert.IsNotNull(list[0] as Foo);
Assert.IsNotNull(list[0] as IBar);
Assert.IsNotNull(list as IList<Foo>);
Assert.IsNotNull((IList<Foo>)list);
}
public void TestMethod1()
{
var list=新列表{new Foo{Name=“Item”};
Assert.IsNotNull(列表为IList);
Assert.IsNotNull(将[0]列为Foo);
Assert.IsNotNull(将[0]列为IBar);
Assert.IsNotNull(列表为IList);
Assert.IsNotNull((IList)列表);
}
IBar是一个接口,因此当您使用List时,最后一个断言将起作用。这一切都与逆变换和协方差有关。简言之,一碗香蕉不是一碗水果,因为允许的操作是不同的。一碗香蕉不允许添加苹果,一碗水果不允许添加苹果。@EricLippert:谢谢这个比喻。这确实有助于说明差异。你应该解释一下为什么Foo
列表不同时也是IBar
列表(请参阅问题注释)。你认为这是理所当然的,尽管这正是OP所要求的。问题是为什么断言失败为什么assert.that(list,is.InstanceOf())代码>返回false?这不是真的吗?谢谢你,马克。协变的可计算性真的帮助了我。@Rohit问题是关于IBar的IList,而不是关于食物的IList是的。我只是好奇,所以想问你。我是否应该为此单独发布一个问题?@Rohit无需;Foo的列表很容易分配给Foo的IList
class Another : IBar {}
IList<IBar> list = new List<Foo>();
list.Add(new Another());
public void TestMethod1()
{
var list = new List<Foo> { new Foo { Name = "Item" } };
Assert.IsNotNull(list as IList);
Assert.IsNotNull(list[0] as Foo);
Assert.IsNotNull(list[0] as IBar);
Assert.IsNotNull(list as IList<Foo>);
Assert.IsNotNull((IList<Foo>)list);
}