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

さて、これをイドしたら…

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 ベースのクラスを定義し、プロパティ ゲッターでストック 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 に答える