Как вы расширяете классы и структуры с помощью интерфейсов через расширение в C #? - PullRequest
0 голосов
/ 08 ноября 2018

Я создаю служебную библиотеку для различных структур данных .Net Framework в C #. Я пытаюсь добавить ICloneable к Dictionary<>. Есть ли способ сделать это через расширение, например, как вы делаете методы расширения?

Для пояснения, в C # вы можете расширять уже существующие классы, создавая "Методы расширения" в статическом классе, например:

public static class MyExtensions
{
    public static void MyArrayExtension<T>(this T[] arg)
    {
        //Your code here...
    }
}

Это позволяет вам выполнять функцию для всех массивов, например:

MyArray.MyArrayExtension();

Вы можете создавать методы расширения для расширения всех классов и структур, в том числе тех, на которые вы ссылаетесь в DLL, например, для .Net Framework. В настоящее время я использую это, чтобы помочь мне спроектировать служебную библиотеку с множеством полезных расширений, которые, по моему мнению, должны были быть реализованы в C #.

При взгляде на System.Linq выясняется, что интерфейсы каким-то образом добавляются в определенные классы структуры данных, такие как Array и List<>, но только когда включено пространство имен. Я пытаюсь выяснить, как это делается, поскольку я не могу найти никаких примеров после поиска в Интернете.

1 Ответ

0 голосов
/ 08 ноября 2018

На данный момент это невозможно.

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

Помните, что проверка поддержки интерфейса может быть записана в существующем коде, подобном этому:

if (dictionary is ICloneable cloneable)
    var clone = cloneable.Clone();

Но это не сработает только с расширением, поскольку базовый тип фактически не реализует интерфейс .


В этой области мысли предпринимаются некоторые усилия:

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


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

public class CloneableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ICloneable
{
    ... methods and properties that delegate to base.XYZ

    public object Clone() => new ...
}

Везде, где вы строите свой объект, вы должны будете написать это:

var dictionary = new CloneableDictionary<...>();

вместо:

var dictionary = new Dictionary<...>();

Поскольку CloneableDictionary наследует Dictionary, вы можете поместить его в переменные и параметры, которые уже существуют, даже если их тип сохраняется как Dictionary<...>, но если вы забудете, что действительно храните в нем другие типы словарей и создавать новые, нормальные, не клонируемые словари, в некоторых местах они могут быстро упасть.

...