C# 索引器属性问题

发布于 2024-07-26 10:00:30 字数 983 浏览 12 评论 0 原文

我有一个像这样的类:

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,我将收到如下错误:

字典中不存在给定的键。

我想要一个可以以与上面相同的方式访问的属性,但在缺少密钥的情况下将返回默认对象。

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

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

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

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

I have a class like this:

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

Now, if Ido this...

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

... and there is no key 13, I will get an error like this:

The given key was not present in the dictionary.

I would like to have a property that can be accessed in the same way as above, but will return a default object in case of the absence of the key.

I tried creating an indexer property like this...

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

... but it looks like that's not a C# 2008 language feature.

How can I access the property in the same way, but get the default object if the key isn't present?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱已欠费 2024-08-02 10:00:30

正如您所发现的,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();
}

C# does not supported named indexers, as you have discovered.

Have you considered using a regular method instead of an indexer property? Not every programming problem requires the use fancy syntax to solve. Yes, you could create your own IDictionary implementation with an aggregated dictionary and change the property access behavior - but is that really necessary for something that just fetches a value or returns a default?

I would add a method like this to your class:

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

or better yet, avoid exception handling as a flow control mechanism:

protected Privilege GetPrivilge( int key )
{
    Privilege priv;
    if( _privileges.TryGetValue( key, out priv ) )
        return priv;
    else
        return new Privilege();
}
揪着可爱 2024-08-02 10:00:30

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

You'll have to define your own IDictionary-based class with an indexer that has the desired behavior, and return an instance of that, rather than the stock Dictionary class, in your property getter.

回首观望 2024-08-02 10:00:30

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

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

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

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

SomeClass foo;
var bar = foo[100];

或者在从 IDictionary (并且内部包含一个 Dictionary 用于实际存储数据)。 然后您可以这样使用它:

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

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

Indexers in C# can only be used with the this keyword.

I suspect you want something like this:

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

which you can define either directly in SomeClass so that you can access a privelege item like:

SomeClass foo;
var bar = foo[100];

or define this indexer in a custom class that implements from IDictionary<TKey, TValue> (and contains a Dictionary<TKey, TValue internally for actually storing the data). You could then use it like:

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

Which is the syntax you seem to propose, and which may be most appropiate, though it takes a bit more effort.

温折酒 2024-08-02 10:00:30

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

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());
    }
}

You should use this syntax to retrieve the value:

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

I have a need for this kind of use of IDictionary a lot, so I made some extension methods:

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

Now you could write:

public Privilege this[int key]
{
    get
    {
        return _privileges.Get(key, () => new Privilege());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文