为什么一个接口实现需要强制转换,而另一个不需要



我今天正在做一些接口工作,当我遇到以下情况时。给定这两个简单的接口:

public interface IItem { }
public interface IInventory
{
    ICollection<IItem> Items { get; }
}

我做了一个简单的类来实现IInventory,并注意到这个实现完全可以写成:

public class BasicInventory1 : IInventory
{
    private Dictionary<int, IItem> items;
    public ICollection<IItem> Items
    {
        get { return items.Values; }
    }
}

但是,此实现需要强制转换:

public class BasicInventory2 : IInventory
{
    private Dictionary<int, IItem> items;
    public ICollection<IItem> Items
    {
        get { return (ICollection<IItem>)items; }
    }
}

为什么一个需要演员,而另一个不需要?检查在这两种情况下返回的两个集合的对象类型,可以确认它们实际上都实现了ICollection

我怀疑这里有一些魔术类型的转换正在进行,因此似乎与协变/逆变有关,但我不太明白到底发生了什么。

Dictionary<int, IItem>没有

实现ICollection<IItem>。就这么简单。

实现该接口是没有意义的,因为如果不指定键,就无法添加到字典中。界面没有意义。

这是一个运行时错误,因为项可以引用字典的子类,以便强制转换可能有效。

我认为如果您要在

第二个示例中添加.Values,则不需要演员表

public class BasicInventory2 : IInventory
{
    private Dictionary<int, IItem> items;
    public ICollection<IItem> Items
    {
       get { return items.Values; }
    }
}

这是因为 items 是一个字典,它实现了ICollection<KeyValuePair<TKey, TValue>> .

此代码无效,并且将始终生成运行时错误:

    public class BasicInventory2 : IInventory
    {
        private Dictionary<int, IItem> items = new Dictionary<int, IItem>();
        public ICollection<IItem> Items
        {
            get
            {
                return (ICollection<IItem>) items;
            }
        }
    }

Dictionary<int, IItem>不实现ICollection<IItem>,而从Dictionary<int, IItem>.Values返回的类型实现。

所以答案是:

第一种情况是可以的Values因为类型正确。

在第二种情况下,编译器知道您正在尝试返回错误的类型,因此它会给您一个编译错误。

如果用案例覆盖错误,则会得到运行时BadCastException

BasicInventory1中,你返回items.Values BasicInventory2你只返回items.Values返回一个ICollection,所以不需要强制转换。

MSDN:

  • 词典

在第二个代码中,使用字典作为返回值,而在第一个代码中使用值。 因此,Dictionary<int,IItems>ICollection<KeyValuePair<int,IItems>>继承ICollection<IItems>。因此,您需要演员阵容。

相关内容

最新更新