2009-07-06 54 views
2

我有這樣一個類:C#索引器屬性問題

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.

我想有一個能以同樣的方式與上述被訪問的屬性,BU如果沒有密鑰,t將返回一個默認對象。

我試圖創建一個索引屬性是這樣的...

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

......但看起來這不是一個C#2008語言功能。

如何以同樣的方式訪問屬性,但如果密鑰不存在則獲取默認對象?

回答

5

您必須使用具有所需行爲的索引器定義您自己的基於IDictionary的類,並在屬性獲取器中返回該實例,而不是股票Dictionary類。

2

Indexers in C#只能與this關鍵字一起使用。

我懷疑你想是這樣的:

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

,你可以定義直接在SomeClass,這樣就可以訪問privelege項目,如:

SomeClass foo; 
var bar = foo[100]; 

或在定義該索引自定義類實現從IDictionary<TKey, TValue>(並在內部包含Dictionary<TKey, TValue實際存儲數據)。然後,您可以像這樣使用它:

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

這是您似乎建議的語法,它可能是最合適的,但它需要更多的努力。

+0

使用異常處理控制流是一個壞理念。它使得你的程序很難調試(因爲通常你想要在第一次機會異常跟蹤的時候進行調試,而且大量無關的異常會使它們變得更難),這使得它們變得很慢,並且它違背了例外情況下的設計事實是例外。最好首先檢查鍵是否存在,而不是嘗試它並在沒有時捕獲異常。 – 2009-07-06 18:27:26

+0

@Eric:很公平 - 我在發佈回覆之前就已經意識到這一點;然而,問題還涉及到問題的屬性/索引方面。您應該在原始問題上發表您的評論。 – Noldorin 2009-07-06 18:31:38

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

這不是有效的C#!索引器只能與`this`關鍵字一起使用。 – Noldorin 2009-07-06 17:38:28

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