C#Indexer属性问题

时间:2009-07-06 17:29:47

标签: c# .net dictionary properties indexer

我有一个这样的课程:

public class SomeClass
{
    private const string sessionKey = "__Privileges";
    public Dictionary<int, Privilege> Privileges
    {
        get
        {
            if (Session[sessionKey] == null)
            {
                Session[sessionKey] = new Dictionary<int, Privilege>();
            }

            return (Dictionary<int, Privilege>)Session[sessionKey];
        }
    }
}

现在,如果我这样......

var someClass = new SomeClass();
var p = someClass.Privileges[13];

...并且没有键13,我会收到这样的错误:

The given key was not present in the dictionary.

我希望有一个可以像上面一样访问的属性,但是如果没有密钥,它将返回一个默认对象。

我尝试创建像这样的索引器属性......

    public Privilege Privileges[int key]
    {
        get
        {
            try { return _privileges[key]; }
            catch { return new Privilege(); }
        }
    }

...但看起来这不是C#2008语言功能。

如何以相同方式访问属性,但如果密钥不存在则获取默认对象?

4 个答案:

答案 0 :(得分:6)

C#不支持命名索引器,正如您所发现的那样。

您是否考虑过使用常规方法而不是索引器属性?并非每个编程问题都需要使用精确的语法来解决。是的,您可以使用聚合字典创建自己的IDictionary实现并更改属性访问行为 - 但是对于只提取值或返回默认值的内容,这是非常必要的吗?

我会在你的班级中添加这样的方法:

protected Privilege GetPrivilege(int key)
{
    try { return _privileges[key]; }
    catch { return new Privilege(); }
}

或者更好的是,避免将异常处理作为流控制机制:

protected Privilege GetPrivilge( int key )
{
    Privilege priv;
    if( _privileges.TryGetValue( key, out priv ) )
        return priv;
    else
        return new Privilege();
}

答案 1 :(得分:5)

您必须使用具有所需行为的索引器定义自己的基于IDictionary的类,并在属性getter中返回该实例,而不是库存Dictionary类。

答案 2 :(得分:2)

C#中的{p> Indexers只能与this关键字一起使用。

我怀疑你想要这样的东西:

public Privilege this[int key]
{
    get
    {
        try { return _privileges[key]; }
        catch { return default(Privelege); }
    }
}

您可以直接在SomeClass中定义,以便您可以访问以下项目:

SomeClass foo;
var bar = foo[100];

或在从IDictionary<TKey, TValue>实现的自定义类中定义此索引器(并在内部包含Dictionary<TKey, TValue以实际存储数据)。然后你可以使用它:

SomeClass foo;
var bar = foo.Priveleges[100];

您似乎建议使用哪种语法,哪种语言可能最合适,但需要花费更多精力。

答案 3 :(得分:-1)

您应该使用此语法来检索值:

public Privilege this[int key]
{
    get
    {
        var value = (Privilege)null;
        if(!_privileges.TryGetValue(key, out value))
            value = new Privilege();
        return value;
    }
}

我需要很多这种IDictionary的使用,所以我做了一些扩展方法:

public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key)
{
    TValue v = default(TValue);
    d.TryGetValue(key, out v);
    return v;
}
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> value)
{
    TValue v = d.Get(key);
    if (v == null)
    {
        v = value();
        d.Add(key, v);
    }
    return v;
}

现在你可以写:

public Privilege this[int key]
{
    get
    {
        return _privileges.Get(key, () => new Privilege());
    }
}