Подтвердить что ты не робот

Почему невозможно определить общие индексы в .NET?

Почему вы не можете создать общий индекс в .NET?

следующий код генерирует ошибку компилятора:

   public T this<T>[string key]
   {
      get { /* Return generic type T. */ }
   }

Означает ли это, что вы не можете создать общий индекс для общей коллекции членов?

4b9b3361

Ответ 1

Единственное, что я могу думать об этом, можно использовать в следующих строках:

var settings = ConfigurationSection.AppSettings;
var connectionString = settings<string>["connectionString"];
var timeout = settings<int>["timeout"];

Но это на самом деле ничего не покупает. Вы только что заменили раунд parens (как в настройках (int) [ "timeout" ]) с помощью угловых скобок, но не получили дополнительной безопасности типа, поскольку вы можете свободно делать

var timeout = settings<int>["connectionString"];

Если у вас есть что-то сильно, но не статически напечатанное, вам может потребоваться дождаться С# 4.0 с его динамическим ключевым словом.

Ответ 2

Здесь место, где это было бы полезно. Скажем, у вас есть строго типизированный OptionKey<T> для объявления параметров.

public static class DefaultOptions
{
    public static OptionKey<bool> SomeBooleanOption { get; }
    public static OptionKey<int> SomeIntegerOption { get; }
}

Если параметры отображаются через интерфейс IOptions:

public interface IOptions
{
    /* since options have a default value that can be returned if nothing's
     * been set for the key, it'd be nice to use the property instead of the
     * pair of methods.
     */
    T this<T>[OptionKey<T> key]
    {
        get;
        set;
    }

    T GetOptionValue<T>(OptionKey<T> key);
    void SetOptionValue<T>(OptionKey<T> key, T value);
}

Затем код мог бы использовать универсальный индекс в качестве красивого строго типизированного хранилища опций:

void Foo()
{
    IOptions o = ...;
    o[DefaultOptions.SomeBooleanOption] = true;
    int integerValue = o[DefaultOptions.SomeIntegerOption];
}

Ответ 3

Свойства не могут быть общими в С# 2.0/3.0, поэтому вы не можете иметь общий индекс.

Ответ 4

Я не знаю, почему, но индексаторы - это просто синтаксический сахар. Вместо этого напишите общий метод, и вы получите ту же функциональность. Например:

   public T GetItem<T>(string key)
   {
      /* Return generic type T. */
   }

Ответ 5

Вы можете; просто отбросьте часть <T> из вашей декларации, и она будет работать нормально. то есть.

public T this[string key]
{
   get { /* Return generic type T. */ }
}

(Предполагая, что ваш класс является общим с параметром типа с именем T).

Ответ 6

Мне нравится возможность иметь индексатора без раздачи прямая ссылка на "индексированный" элемент. Я написал простой "перезванивать" класс индексатора ниже...

R = возвращаемый тип из индексатора P = переданный тип в индекс

Весь индекс, который действительно выполняет, передает операции развертыватель и разрешить им управлять тем, что на самом деле происходит и возвращается.

public class GeneralIndexer<R,P>
    {
        // Delegates
        public delegate R gen_get(P parm);
        public delegate void gen_set(P parm, R value);
        public delegate P[] key_get();

        // Events
        public event gen_get GetEvent;
        public event gen_set SetEvent;
        public event key_get KeyRequest;

        public R this[P parm]
        {
            get { return GetEvent.Invoke(parm); }
            set { SetEvent.Invoke(parm, value); }
        }

        public P[] Keys
        {
            get
            {
                return KeyRequest.Invoke();
            }
        }

    }

Чтобы использовать его в программе или классе:

private GeneralIndexer<TimeSpan, string> TimeIndex = new GeneralIndexer<TimeSpan,string>();

{
            TimeIndex.GetEvent += new GeneralIndexer<TimeSpan, string>.gen_get(TimeIndex_GetEvent);
            TimeIndex.SetEvent += new GeneralIndexer<TimeSpan, string>.gen_set(TimeIndex_SetEvent);
            TimeIndex.KeyRequest += new GeneralIndexer<TimeSpan, string>.key_get(TimeIndex_KeyRequest);

}

работает как чемпион, особенно если вы хотите контролировать доступ к ваш список или какие-либо специальные операции, когда что-то доступно.