c# – 为什么我不能通过索引访问KeyedCollection项目?

我有这个代码(我希望它可以工作,但它失败了)..我真的不知道为什么.请帮忙

static void Main(string[] args)
    {
        var x = new MyKeyedCollection();

        x.Add(new MyType() { Key = 400L,Value = 0.1 });
        x.Add(new MyType() { Key = 200L,Value = 0.1 });
        x.Add(new MyType() { Key = 100L,Value = 0.1 });
        x.Add(new MyType() { Key = 300L,Value = 0.1 });

        //foreach (var item in x)
        for (int i = 0; i < x.Count; i++)
        {
            //Debug.WriteLine(item.PriceLevel);
            Debug.WriteLine(x[i].Key);
        }
    }
}

public class MyType 
{
    public long Key;
    public double Value;
}

public class MyKeyedCollection : KeyedCollection<long,MyType>
{
    protected override long GetKeyForItem(MyType item)
    {
        return item.Key;
    }
}

例外:

System.Collections.Generic.KeyNotFoundException was unhandled
Message=The given key was not present in the dictionary.
Source=mscorlib StackTrace:
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary2.get_Item(TKey key)
at System.Collections.ObjectModel.KeyedCollection
2.get_Item(TKey
key)

at KeyedCollectionTest.Program.Main(String[] args) in …\Program.cs:line 25
at System.AppDomain._nExecuteAssembly(Assembly assembly,String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state)
at System.Threading.ThreadHelper.ThreadStart() InnerException:

为什么它试图获得Key而不是索引?键明显很长而不是int.我确信之前我使用过KeyedCollection,它对long key和int index工作得很好.

我尝试在ver 2,3,4,4.5中编译(使用VS2012)…

别搞定.

解决方法

How come it tries to get Key instead of index? Key is clearly long and not int.

但是int可以转换为long,所以它是一个有效的候选成员.

问题是这个[TKey key]索引器最初在KeyedCollection中声明,而this [int index]索引器最初在Collection中声明.重载决策规则指定首先搜索最派生的类,并且只考虑首先在该类型中声明的成员.只有当搜索失败时,编译器才会向上移动到类型层次结构中的下一级别.

所以,如果你写:

Collection<MyType> collection = x;
for (int i = 0; i < x.Count; i++)
{
    Debug.WriteLine(collection[i].Key);
}

它将起作用 – 因为编译时类型的集合只是Collection< T>,它只有“int index”索引器.

这是一个示例,它显示了相同的行为,而不使用泛型,索引器或抽象类:

using System;

class Base
{
    public void Foo(int x)
    {
        Console.WriteLine("Base.Foo(int)");
    }
}

class Derived : Base
{
    public void Foo(long y)
    {
        Console.WriteLine("Derived.Foo(long)");
    }
}

class Program
{
    static void Main()
    {
        Derived x = new Derived();
        Base y = x;
        x.Foo(5); // Derived.Foo(long)
        y.Foo(5); // Base.Foo(int)
    }
}

有关更多有趣的规则,请参阅我的article on overloading.

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...