C # Indexer Свойство Вопрос

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

... но похоже, что это не язык языка С# 2008.

Как я могу получить доступ к свойству таким же образом, но получить объект по умолчанию, если ключ отсутствует?

Теги:
dictionary
properties

4 ответа

5
Лучший ответ

Вам нужно будет определить свой собственный класс на основе IDictionary с индексом, который имеет желаемое поведение, и вернуть экземпляр этого, а не класса словаря запасов в ваш получатель.

6

С# не поддерживает названные индексы, как вы обнаружили.

Рассматривали ли вы использование обычного метода вместо свойства индексатора? Не каждая проблема программирования требует использования мозаичного синтаксиса для решения. Да, вы могли бы создать свою собственную реализацию 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();
}
  • 0
    Хороший совет. Я воспользовался вашим советом, чтобы решить мою проблему. Раньше я использовал обработку исключений для управления потоком, но до сих пор не думал об этом как о плохой вещи. Благодарю.
2

Индексаторы на С# могут использоваться только с ключевым словом 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
    Использование обработки исключений в качестве потока управления - плохая идея. Это делает ваши программы трудными для отладки (потому что часто вы хотите отлаживать их при первом отслеживании исключений, а множество посторонних исключений делает это сложнее), делает их медленными и работает против того факта, что исключения должны быть исключительным Лучше вместо этого сначала проверить, существует ли ключ, чем пытаться его найти и перехватить исключение, когда его нет.
  • 0
    @Eric: Очень справедливо - я знал об этом до того, как опубликовал ответ; однако вопрос касался, кроме того, аспекта свойства / индексатора вопроса. Вы, вероятно, должны оставить свой комментарий на оригинальный вопрос.
-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 .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню