3

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

     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 未处理
Message=字典中不存在给定的键。
Source=mscorlib StackTrace:在 System.Collections.Generic.Dictionary 的 System.ThrowHelper.ThrowKeyNotFoundException() 2.get_Item(TKey key) at System.Collections.ObjectModel.KeyedCollection2. ...\Program.cs:line 中 KeyedCollectionTest.Program.Main(String[] args) 的get_Item(TKey key) 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() 内部异常:

为什么它会尝试获取 Key 而不是索引?密钥显然很长,而不是 int。我确信我之前使用过 KeyedCollection,它对于长键和 int 索引工作得很好。

我尝试在版本 2、3.5、4、4.5 中编译(使用 VS2012)...

不明白。

4

4 回答 4

7

为什么它会尝试获取 Key 而不是索引?密钥显然很长,而不是 int。

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

问题是this[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是 just 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)
    }
}

有关更多涉及的有趣规则,请参阅我关于重载的文章。

于 2013-01-15T20:52:59.407 回答
0
class Program
{
    static void Main(string[] args)
    {
        var x = new MyKeyedCollection();

        x.Add(new MyType() { Key = 110L, Value = 0.1 });
        x.Add(new MyType() { Key = 122L, Value = 0.1 });
        x.Add(new MyType() { Key = 233L, Value = 0.1 });
        x.Add(new MyType() { Key = 344L, Value = 0.1 });

        foreach(int key in x.Keys())
        {   
            Console.WriteLine(x[key].Key);
        }

        Console.Read();
    }
}

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

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

    public IEnumerable<long> Keys()
    {
        foreach (MyType item in this.Items)
        {
            yield return GetKeyForItem(item);
        }
    }
}

迭代键的方法不会在这里解决问题,还是我遗漏了什么?

于 2013-01-16T12:10:22.593 回答
0

您也可以简单地使用:

Debug.WriteLine(x.ElementAt(i).Key);

“ElementAt”允许您检索指定索引处的元素。如果您的键是 int 类型,这会很好地工作。

于 2013-03-27T18:55:03.163 回答
0

如果您尝试确定如何通过索引访问 KeyedCollection 项目(如果您已将其键入),则此页面确实会出现在搜索结果中int,因此在此处回答该问题可能很有用。你这样做:

myKeyedCollectionInstance.Items[index];

index一个在哪里int.Items是因为IList, 和 is protected,所以要使它在类和继承自它的类之外可用,您必须添加一个publicorinternal访问器方法,如下所示:

internal new IList<Occupation> AllItems
{
    get { return this.Items; }
}
于 2017-02-01T09:50:12.920 回答