Переопределение невиртуального метода
От: Pek2014 Россия  
Дата: 19.04.17 13:32
Оценка:
Хочется странного?...

Задачка. В обычном Dictionary<> не устраивает реализация метода Add. Надо кое-что в него добавить (некую диагностику). В остальном стандартный Dictionary<> вполне устраивает.

Унаследоваться и переопределить метод Add не выходит. Метод не виртуальный. Видится два выхода:

Выход 1. Написать свой новый внешний статический метод (например AddValue) и заменить все вызовы старого Add на новый AddValue (можно сделать как extention метод для красоты).

Выход 2. Написать свой Dictionary агрегировав стандартный и тупо перенаправив ему все вызовы, подкрутив немного метод Add.


Выход 1 не устраивает тем, что надо поправить очень большое число мест использования привычного метода Add на нестандартный.

Выход 2 Хорош тем, что требует исправления клиентского кода только в месте создания словаря, а код в местах его использования не меняется. Но плох тем, что надо написать кучу тупого кода, повторяя вполне устраивающую функциональность стандартного словаря.

Нет ли ещё какого способа "переопределить" невиртуальный метод?
Отредактировано 19.04.2017 13:40 Pek2014 . Предыдущая версия .
Re: Переопределение невиртуального метода
От: QrystaL Украина  
Дата: 19.04.17 13:44
Оценка:
Здравствуйте, Pek2014, Вы писали:
P>Нет ли ещё какого способа "переопределить" невиртуальный метод?

public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IDictionary<TKey, TValue>
{
    public void Add(TKey key, TValue value)
    {
        // ...
        base.Add(key, value);
        // ...
    }
}


В клиентском коде использовать через IDictionary.
Re[2]: Переопределение невиртуального метода
От: Pek2014 Россия  
Дата: 19.04.17 14:58
Оценка:
Здравствуйте, QrystaL, Вы писали:

QL>Здравствуйте, Pek2014, Вы писали:

P>>Нет ли ещё какого способа "переопределить" невиртуальный метод?

QL>
QL>public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IDictionary<TKey, TValue>
QL>{
QL>    public new  void Add(TKey key, TValue value)
QL>    {
QL>        // ...
QL>        base.Add(key, value);
QL>        // ...
QL>    }
QL>}
QL>


QL>В клиентском коде использовать через IDictionary.


Да. Но теперь надо заставить (убедиться, быть уверенным что...) пользоваться только IDictionary?
Просматривать и анализировать код — это не метод. Что нибудь да пропустим...

Вот такой вариант... странноватый?...
public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IDictionary<TKey, TValue>
{
    public new void Add(TKey key, TValue val)
    {
        // ...
        base.Add(key, val);
        // ...
    }

    public static IDictionary<TKey, TValue> Create() => new MyDictionary<TKey, TValue>();
    public static IDictionary<TKey, TValue> Create(int capacity) => new MyDictionary<TKey, TValue>(capacity);
    public static IDictionary<TKey, TValue> Create(IEqualityComparer<TKey> comparer) => new MyDictionary<TKey, TValue>(comparer);
    public static IDictionary<TKey, TValue> Create(IDictionary<TKey, TValue> dictionary) => new MyDictionary<TKey, TValue>(dictionary);
    public static IDictionary<TKey, TValue> Create(int capacity, IEqualityComparer<TKey> comparer) => new MyDictionary<TKey, TValue>(capacity, comparer);
    public static IDictionary<TKey, TValue> Create(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) => new MyDictionary<TKey, TValue>(dictionary, comparer);


    private MyDictionary() { }
    private MyDictionary(int capacity) : base(capacity) { }
    private MyDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }
    private MyDictionary(IDictionary<TKey, TValue> dictionary) : base(dictionary) { }
    private MyDictionary(int capacity, IEqualityComparer<TKey> comparer) : base(capacity, comparer) { }
    private MyDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : base(dictionary, comparer) { }
}
...
var mydic = MyDictionary<string, string>.Create();
mydic.Add("a", "123");
...
Re: Переопределение невиртуального метода
От: Sinatr Германия  
Дата: 20.04.17 06:57
Оценка: +1
Здравствуйте, Pek2014, Вы писали:

P> В обычном Dictionary<> не устраивает реализация метода Add. Надо кое-что в него добавить (некую диагностику).


Почему в этот метод? Словарь — это что-то низкоуровневое (по-сути примитив типа массива). О какой именно диагностике идет речь? Отладке?

Вы уже предложили extension method, тоесть думаете в правильном направлении. Добавляйте что там вам необходимо в методы, которые используют какойто определенный экземпляр словаря (а не все подряд). Можно перед каждым вызовом (удобнее всего с помочью extension method). Отговорки в стиле "надо править слишком большое число мест" звучат не очень убедительно, ведь именно так подобная задача и решается, переопределить невертуальный метод — звучит как XY проблема.
---
ПроГLамеры объединяйтесь..
Re[2]: Переопределение невиртуального метода
От: Pek2014 Россия  
Дата: 20.04.17 09:17
Оценка:
Здравствуйте, Sinatr, Вы писали:

P>> В обычном Dictionary<> не устраивает реализация метода Add. Надо кое-что в него добавить (некую диагностику).


S>Вы уже предложили extension method... Отговорки в стиле "надо править слишком большое число мест" звучат не очень убедительно, ведь именно так подобная задача и решается,


Задача в том, чтобы программист, получивший ссылку на словарь действовал "как обычно", "как привычно", ничего не подозревая, но из-за фокуса сделанного в момент создания словаря (где-то далеко по коду), результат был бы "особенный".

S>...переопределить невиртуальный метод — звучит как XY проблема.


И тем не менее это сделать удалось с помощью повторной реализации интерфейса.
А доступ к старой версии метода (тому, что был перед переопределением),удалось (пришлось) блокировать запретом прямого создания экземпляров класса и предоставлением конкретной фабрики.
Отредактировано 20.04.2017 9:44 Pek2014 . Предыдущая версия . Еще …
Отредактировано 20.04.2017 9:18 Pek2014 . Предыдущая версия .
Отредактировано 20.04.2017 9:18 Pek2014 . Предыдущая версия .
Re: Переопределение невиртуального метода
От: Doc Россия http://andrey.moveax.ru
Дата: 22.04.17 05:53
Оценка:
Здравствуйте, Pek2014, Вы писали:

P>Выход 1. Написать свой новый внешний статический метод (например AddValue) и заменить все вызовы старого Add на новый AddValue (можно сделать как extention метод для красоты).

P>Выход 2. Написать свой Dictionary агрегировав стандартный и тупо перенаправив ему все вызовы, подкрутив немного метод Add.

Если там где он используется код не time-critical с кучей вызовов за короткое время то второй вариант в поддержке будет удобнее. Хотя все равно придется следить чтобы не создавали стандартный Dictionary.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.