2

我有这样的课:

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];
        }
    }
}

现在,如果 Ido 这个...

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

4 回答 4

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();
}
于 2009-07-06T18:49:19.167 回答
5

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

于 2009-07-06T17:31:53.877 回答
2

C# 中的索引器只能与this关键字一起使用。

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

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

您可以直接在其中定义,SomeClass以便您可以访问特权项目,例如:

SomeClass foo;
var bar = foo[100];

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

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

您似乎建议使用哪种语法,并且可能最合适,尽管它需要更多的努力。

于 2009-07-06T17:33:40.830 回答
-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());
    }
}
于 2009-07-06T17:37:05.660 回答