Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多态性-我没有得到什么?_C#_C# 4.0_Polymorphism - Fatal编程技术网

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

我对C#中的多态性有问题。我有一个实现接口的对象,但我不能将对象的集合表示为接口的集合。这与我对多态性的理解背道而驰。所以我想知道我哪里做错了

[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);
}