Вопрос по дженерикам
От: Аноним  
Дата: 21.09.09 10:33
Оценка:
Привет.
Можно ли делать Events в виде дженериков? Суть в том что есть сообщение об изменении параметров, вот эти параметры могут быть различных типов.
Сделал вот так
public delegate void ParameterChangeDelegate<T>(MyEventArgs<T> e); 
        public event ParameterChangeDelegate<float> OnFloatParameterChange;
        public event ParameterChangeDelegate<String> OnStringParameterChange;
        public event ParameterChangeDelegate<Int32> OnIntParameterChange;

но так на каждый тип придется добавлять Event. Не хочется так

И еще.
Допустим есть класс, который хранит имя параметра и допустимые значения, что то типа такого
class Param<T>
{
 String Name;
 List<T> Values;
}

Хочу хранить эти параметры в List<Param>.
Что же теперь для хранения каждого параметра нужно заводить отдельный Param<int>, Param<String>?
Или можно сделать как нибудь по другому??
Re: Вопрос по дженерикам
От: _FRED_ Черногория
Дата: 21.09.09 15:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет.

А>Можно ли делать Events в виде дженериков? Суть в том что есть сообщение об изменении параметров, вот эти параметры могут быть различных типов.
А>Сделал вот так
А>public delegate void ParameterChangeDelegate<T>(MyEventArgs<T> e); 
А>public event ParameterChangeDelegate<float> OnFloatParameterChange;
А>public event ParameterChangeDelegate<String> OnStringParameterChange;
А>public event ParameterChangeDelegate<Int32> OnIntParameterChange;

А>но так на каждый тип придется добавлять Event. Не хочется так

Тогда альтернатива:

public event ParameterChangeDelegate<object> OnParameterChange


Кстати, обычно такие события именую как Changed или Changing, в зависимости от того, приходят они после фактического изменения значения (первый вариант) или перед изменением (часто, аргументы таких событий позволяют отменить грядущее изменение).

А>И еще.

А>Допустим есть класс, который хранит имя параметра и допустимые значения, что то типа такого
А>class Param<T>
А>{
А>  String Name;
А>  List<T> Values;
А>}

А>Хочу хранить эти параметры в List<Param>.
А>Что же теперь для хранения каждого параметра нужно заводить отдельный Param<int>, Param<String>?
А>Или можно сделать как нибудь по другому??

Вариантов несколько. Основное — надо предоставить типонезависимый доступ к экземпляру Param. Например, так:

interface IParam
{
  String Name { get; set; }
  ReadOnlyCollection<object> Values { get; set; }
}

А>class Param<T> : IParam
А>{
    private IList<T> values;
    private ReadOnlyCollection<object> readOnlyValues;

А>  String Name { get; set;} // сделаем эти члены свойствами, а не полями

А>  List<T> Values { 
      get { return values; } 
      set { 
        values = value; 
        readOnlyValues = null; 
      } 
    }

    ReadOnlyCollection<object> IParam.Values { 
      get { return readOnlyValues ?? (readOnlyValues = CreateReadOnlyCollection(Values)); }
      set { Values = GetWritableCollection(value); /* тут возможно "непонятка", но её не избежать */ }
    }
А>}


Код методов CreateReadOnlyCollection и GetWritableCollection достаточно прост, напиши, если не справишся и он понадобится, завтра подскажу.

"Непонятка" состоит в том, что такой вот код, к удивлению, не сработает:
ReadOnlyCollection<object> collection = …;
IParam param = …;
param.Values = collection;
Debug.Assert(param.Values == collection, "param.Values == collection");

но её не избежать — надо изменить интерфейс Param<T> или IParam. Как это сделать лучше — предсказать не возьмусь без детального знания имеющегося и требуемого кода.

P.S. Давай всё-таки повнимательней с оформлением кода в сообщениях — когда хочешь написать аккуратный ответ и приходится исправлять форматирование спрашивающего, то на ум приходит много интересных слов :о)
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Вопрос по дженерикам
От: Аноним  
Дата: 22.09.09 07:32
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тогда альтернатива:


_FR>
_FR>public event ParameterChangeDelegate<object> OnParameterChange
_FR>


А каким образом лучше узнавать какого типа этот object??

if (typeof(Int32).Equals(obf.GetType()))


_FR>Кстати, обычно такие события именую как Changed или Changing, в зависимости от того, приходят они после фактического изменения значения (первый вариант) или перед изменением (часто, аргументы таких событий позволяют отменить грядущее изменение).

Спасибо

_FR>Вариантов несколько. Основное — надо предоставить типонезависимый доступ к экземпляру Param. Например, так:


_FR>
_FR>interface IParam
_FR>{
_FR>  String Name { get; set; }
_FR>  ReadOnlyCollection<object> Values { get; set; }
_FR>}

А>>class Param<T> : IParam
А>>{
_FR>    private IList<T> values;
_FR>    private ReadOnlyCollection<object> readOnlyValues;

А>>  String Name { get; set;} // сделаем эти члены свойствами, а не полями

А>>  List<T> Values { 
_FR>      get { return values; } 
_FR>      set { 
_FR>        values = value; 
_FR>        readOnlyValues = null; 
_FR>      } 
_FR>    }

_FR>    ReadOnlyCollection<object> IParam.Values { 
_FR>      get { return readOnlyValues ?? (readOnlyValues = CreateReadOnlyCollection(Values)); }
_FR>      set { Values = GetWritableCollection(value); /* тут возможно "непонятка", но её не избежать */ }
_FR>    }
А>>}
_FR>


Ага, тоесть "наружу" мы предоставляем список с типом object а внутри у нас список с указанным типом T?

_FR>Код методов CreateReadOnlyCollection и GetWritableCollection достаточно прост, напиши, если не справишся и он понадобится, завтра подскажу.


Что то типа такого??
        private ReadOnlyCollection<Object> CreateReadOnlyCollection(List<T> value)
        {
            return value.ConvertAll<Object>(TToObject).AsReadOnly();
        }

        public static Object TToObject(T val)
        {
            return (Object)val;
        }



_FR>"Непонятка" состоит в том, что такой вот код, к удивлению, не сработает:

_FR>
_FR>ReadOnlyCollection<object> collection = …;
_FR>IParam param = …;
_FR>param.Values = collection;
_FR>Debug.Assert(param.Values == collection, "param.Values == collection");
_FR>

_FR>но её не избежать — надо изменить интерфейс Param<T> или IParam. Как это сделать лучше — предсказать не возьмусь без детального знания имеющегося и требуемого кода.

Тоесть доступ к Values нам надо получать через приведение к интерфейсу??
Тогда вот такой код компилируется

            Param<int> paramInt = new Param<int>();
            ((IParam)paramInt).Values = new ReadOnlyCollection<object>(new object[] { "1", "2", "3", "4", "5", "6", "7" });



_FR>P.S. Давай всё-таки повнимательней с оформлением кода в сообщениях — когда хочешь написать аккуратный ответ и приходится исправлять форматирование спрашивающего, то на ум приходит много интересных слов :о)

Посыпаю голову пеплом
Re[3]: Вопрос по дженерикам
От: _FRED_ Черногория
Дата: 22.09.09 08:44
Оценка:
Здравствуйте, Аноним, Вы писали:

_FR>>Тогда альтернатива:

_FR>>public event ParameterChangeDelegate<object> OnParameterChange


А>А каким образом лучше узнавать какого типа этот object??


Результатом операции "какого типа" должен быть тип, поэтому правильный ответ "obj.GetType()"

А>if (typeof(Int32).Equals(obf.GetType()))


Узнать, записано ли в переменной значение, которое имеет тип int можно так: "obj is int".

_FR>>Вариантов несколько. Основное — надо предоставить типонезависимый доступ к экземпляру Param. Например, так:


А>Ага, тоесть "наружу" мы предоставляем список с типом object а внутри у нас список с указанным типом T?


Что с наружи, что изнутри, тебе виднее, но на — там, где требуется типизированный подход, предоставляем типизтрованный интерфейсж; там, где нужен не-типизтрованный, используем object и т.п. Одно ограничение — нетипизированный список я сделал read-only, можно и не-ридонли, но могут возникнуть ошибки, когда в нетипизированный список добавят данные неожидаемого типа.

_FR>>Код методов CreateReadOnlyCollection и GetWritableCollection достаточно прост, напиши, если не справишся и он понадобится, завтра подскажу.

А>Что то типа такого??

Ага

А>Тоесть доступ к Values нам надо получать через приведение к интерфейсу??

А>Тогда вот такой код компилируется
А>            Param<int> paramInt = new Param<int>();
А>            ((IParam)paramInt).Values = new ReadOnlyCollection<object>(new object[] { "1", "2", "3", "4", "5", "6", "7" });


Именно в таком виде данный код использовать нецелесообразно — у переменной paramInt есть типизированные Values. А вообще: код, которому нужен нетипизированный доступ должен работать через интерфейс. При этом явное "приведение к интерфейсу" делать не нужно. Например, у нас есть Param<int> и метод, который требует нетипизированный IParam:

void Method(IParam param) {
  foreach(var item in param.Values) {
    // some work…
  }//for
}

void Method2() {
  var paramInt = new Param<int>();
  Method(paramInt); /* никакого "явного приведения к интерфейсу" */
}
Help will always be given at Hogwarts to those who ask for it.
Re: Вопрос по дженерикам
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.09.09 06:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет.

А>Можно ли делать Events в виде дженериков? Суть в том что есть сообщение об изменении параметров, вот эти параметры могут быть различных типов.
Нет. Свойства и события не могут быть обобщёнными.

А>но так на каждый тип придется добавлять Event. Не хочется так

А зачем? Каким обработчиком будут обрабатываться эти евенты?
Если будет один обработчик на всех, то нужно делать object. Если обработчик должен вешаться на конкретный параметр, то это будет отдельное событие, а у конкретного параметра всегда есть тип.
Единственное, для чего такое подходит — это обработчики типа "изменения всех целых параметров". Непохоже, чтобы это имело физический смысл.
Но для него можно эмулировать event. Это же всего лишь пара методов — Add и Remove.

А>И еще.

А>Допустим есть класс, который хранит имя параметра и допустимые значения, что то типа такого
А>
А>class Param<T>
А>{
А> String Name;
А> List<T> Values;
А>}
А>

А>Хочу хранить эти параметры в List<Param>.
Для чего? Какая обработка планируется для этого списка? Есть подозрение, что можно обойтись object там, где вы пишете T.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Вопрос по дженерикам
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 24.09.09 15:10
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Можно ли делать Events в виде дженериков?


То, что в шарпе обозначается ключевым словом event — нельзя.

А>но так на каждый тип придется добавлять Event. Не хочется так


public IDisposable SubscribeParameterChanged<T>(ParameterChangeDelegate<T> changeHandler) {...}

Идея понятна?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237 on Windows 7 6.1.7100.0>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.