none
Создание массива дженерик делегатов RRS feed

  • Вопрос

  • Подскажите, если ли возможность создавать массивы с дженерик делегатами внутри.

    Пример:

    В классе есть 2 дженерик метода, которые удовлетворяют описанию делегата delegate bool ValidateValues<T>(T Val, TAval, TBval)

    private bool Validation1<T>(T Val, T AVal, T BVal) where T : System.IComparable<T>
    {
    ...
    }
    private bool Validation2<T>(T Val, T AVal, T BVal) where T : System.IComparable<T>
    {
    ...
    }

    Эти 2 метода я хочу вызывать по некоторому индексу, который приходит из внешнего источника. Первый бы вариант был написать case, и по индексу вызывать нужный мне метод. Второй вариант, как раз который бы хотелось реализовать, это вытаскивание делегата этих методов из массива , и их вызов, что безусловно сэкономило бы количество необходимого для поддержания кода (про скорость сомневаюсь, case скорее всего конечно быстрее).

    Как создавать массив НЕ дженерик делегатов я понимаю, а вот с Дженериками нет, потому как при попытке создания массива с типом ValidateValues<T> от меня естественно компилятор требует явно задать тип, а это сразу же убивают всю идею об использовании дженерик методов.

    Если я не прав в своих рассуждениях, поправьте.

    4 ноября 2010 г. 7:21

Ответы

  • Массив дженериков без указания типа сделать нельзя. Но можно сделать дженериком весь класс, тогда ты сможешь использовать дженерик параметр класса при объявлении свойства-массива.

    public class ValidationLib<T> where T : IComparable<T>
    {
      public ValidationLib()
      {
        this.Validations = new Func<T,T,T,bool>[] { this.Validation1, this.Validation2 };
      }
    
      public Func<T, T, T, bool>[] Validations {get; private set;}
    
      private bool Validation1(T Val, T AVal, T BVal)
      {
        return false;
      }
      private bool Validation2(T Val, T AVal, T BVal)
      {
        return true;
      }
    }
    
    class Program
    {
      static void Main(string[] args)
      {
        var lib = new ValidationLib<int>();
        Console.WriteLine(lib.Validations[0](1, 2, 3));
        Console.WriteLine(lib.Validations[1](1, 2, 3));
      }
    }
    
    

    Или можно сделать метод, инициализирующий массив для конкретного типа, и возвращающий его:

    public class ValidationLib
    {
      private bool Validation1<T>(T Val, T AVal, T BVal) where T : IComparable<T>
      {
        return false;
      }
      private bool Validation2<T>(T Val, T AVal, T BVal) where T : IComparable<T>
      {
        return true;
      }
    
      public Func<T, T, T, bool>[] GetValidators<T>() where T : IComparable<T>
      {
        return new Func<T, T, T, bool>[] { Validation1, Validation2 };
      }
    }
    
    class Program
    {
      static void Main(string[] args)
      {
        var validators = new ValidationLib().GetValidators<int>();
        Console.WriteLine(validators[0](1, 2, 3));
        Console.WriteLine(validators[1](1, 2, 3));
      }
    }
    

    • Помечено в качестве ответа Eugene Olisevich 5 ноября 2010 г. 7:43
    4 ноября 2010 г. 18:42
    Модератор

Все ответы

  • Массив дженериков без указания типа сделать нельзя. Но можно сделать дженериком весь класс, тогда ты сможешь использовать дженерик параметр класса при объявлении свойства-массива.

    public class ValidationLib<T> where T : IComparable<T>
    {
      public ValidationLib()
      {
        this.Validations = new Func<T,T,T,bool>[] { this.Validation1, this.Validation2 };
      }
    
      public Func<T, T, T, bool>[] Validations {get; private set;}
    
      private bool Validation1(T Val, T AVal, T BVal)
      {
        return false;
      }
      private bool Validation2(T Val, T AVal, T BVal)
      {
        return true;
      }
    }
    
    class Program
    {
      static void Main(string[] args)
      {
        var lib = new ValidationLib<int>();
        Console.WriteLine(lib.Validations[0](1, 2, 3));
        Console.WriteLine(lib.Validations[1](1, 2, 3));
      }
    }
    
    

    Или можно сделать метод, инициализирующий массив для конкретного типа, и возвращающий его:

    public class ValidationLib
    {
      private bool Validation1<T>(T Val, T AVal, T BVal) where T : IComparable<T>
      {
        return false;
      }
      private bool Validation2<T>(T Val, T AVal, T BVal) where T : IComparable<T>
      {
        return true;
      }
    
      public Func<T, T, T, bool>[] GetValidators<T>() where T : IComparable<T>
      {
        return new Func<T, T, T, bool>[] { Validation1, Validation2 };
      }
    }
    
    class Program
    {
      static void Main(string[] args)
      {
        var validators = new ValidationLib().GetValidators<int>();
        Console.WriteLine(validators[0](1, 2, 3));
        Console.WriteLine(validators[1](1, 2, 3));
      }
    }
    

    • Помечено в качестве ответа Eugene Olisevich 5 ноября 2010 г. 7:43
    4 ноября 2010 г. 18:42
    Модератор
  • Да, спасибо за варианты решений. Сам через некоторое время выбрал решение, написанное во втором варианте.
    Олисевич Евгений Александрович. ЗАО "ПРОГНОЗ"
    5 ноября 2010 г. 7:43