首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我不能逐项访问KeyedCollection?

为什么我不能逐项访问KeyedCollection?
EN

Stack Overflow用户
提问于 2013-01-15 20:47:21
回答 4查看 2.5K关注 0票数 3

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

代码语言:javascript
复制
     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=The。 System.ThrowHelper.ThrowKeyNotFoundException() at System.Collections.Generic.Dictionary2.get_Item(TKey key) at System.Collections.ObjectModel.KeyedCollection2.get_Item(TKey key) at KeyedCollectionTest.Program.Main(String[] args)在...\Program.cs:line 25 at System.AppDomain._nExecuteAssembly(组装,String[] args)在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态) at System.Threading.ThreadHelper.ThreadStart() InnerException:

为什么它试图获取键而不是索引?键显然是长的,而不是int。我确信我以前使用过KeyedCollection,它在长键和int索引中工作得很好。

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

别弄明白。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-15 20:52:59

为什么它试图获取键而不是索引?键显然是长的,而不是int。

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

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

所以如果你写:

代码语言:javascript
复制
Collection<MyType> collection = x;
for (int i = 0; i < x.Count; i++)
{
    Debug.WriteLine(collection[i].Key);
}

因为编译时类型的collection只是Collection<T>,它只有"int索引“索引器。

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

代码语言:javascript
复制
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

票数 7
EN

Stack Overflow用户

发布于 2013-01-16 12:10:22

代码语言:javascript
复制
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);
        }
    }
}

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

票数 0
EN

Stack Overflow用户

发布于 2013-03-27 18:55:03

您还可以简单地使用:

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14346616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档