Можно ли ограничить параметр универсального типа для String OR Array - PullRequest
9 голосов
/ 14 января 2012

Вкратце: возможно ли определить универсальный метод, в котором параметр типа (T) ограничен string или int[]? В псевдо-C # я хочу сделать следующее:

public static int MyMethod<T> ( T arg1, T arg2 ) 
    where T : (has an indexer that returns an int) {
    // stuff with arg1[i], arg2[j], etc...
}

Обратите внимание, что в C # из-за встроенного индексатора string (который возвращает char) наряду с неявным преобразованием из char в int следующее выражение означает точно то же самое, будь то source это string или int[]:

int someval = source[index];

По потоку Ограничить универсальный метод расширения базовыми типами и строкой Я понимаю, что не могу просто сделать список несвязанных типов в предложении ограничения where T : x.... И int[], и string будут соответствовать T: IEnumerable<int>, но IEnumerable<T> не требует, чтобы разработчики имели индексатор, что является в точности общей чертой, которую я использую в обоих типах.

Цель этого заключается в том, что я создаю несколько высоко оптимизированных функций анализа и анализа строк, таких как быстрая реализация алгоритма расстояния Дамерау – Левенштейна. Я обнаружил, что первое преобразование моих строк в массивы int может иногда приводить к значительно более быстрым выполнениям при повторяющейся посимвольной обработке (как в алгоритме D-L). Во многом это связано с тем, что сравнение int значений намного быстрее, чем сравнение char значений.

Действующее слово «иногда». Иногда быстрее работать непосредственно со строками и избежать затрат на первое преобразование и копирование в массивы int. Теперь у меня есть методы, которые действительно идентичны, за исключением объявлений.

Конечно, я могу использовать dynamic, но снижение производительности из-за проверки во время выполнения полностью уничтожает любые выгоды, полученные при построении методов. (Я сделал проверить это).

Ответы [ 3 ]

5 голосов
/ 14 января 2012

У вас не может быть ограничения, которое говорит, что «тип должен иметь индексатор».

Однако, у вас может быть ограничение, которое говорит, что «тип должен реализовывать интерфейс, который имеет индексатор».Такой интерфейс может быть, например, IList<char>.

К сожалению, string не реализует IList<char>, поэтому вам придется написать для него небольшой класс-оболочку:

sealed class StringWrapper : IList<char>
{
    public string String { get; private set; }
    public StringWrapper(string str) { String = str; }
    public static implicit operator StringWrapper(string str)
    {
        return new StringWrapper(str);
    }

    public char this[int index]
    {
        get { return String[index]; }
        set { throw new NotSupportedException(); }
    }

    // Etc.... need to implement all the IList<char> methods
    // (just throw NotSupportedException except in the ones that are trivial)
}

И тогда вы можете объявить свой метод следующим образом:

public static TElement MyMethod<TCollection, TElement>(TCollection arg)
    where TCollection : IList<TElement>
{
    return arg[0];
}

[...]

MyMethod<StringWrapper, char>("abc")     // returns 'a'
MyMethod<int[], int>(new[] { 1, 2, 3 })  // returns 1
5 голосов
/ 14 января 2012

Нет, C # не позволяет вам создавать «составное» ограничение, подобное этому.

Выражение, которое вы показываете, означает то же самое, но вы не можете использовать этот факт в своих интересах.Обобщения C # синтаксически напоминают шаблоны C ++, но работают совершенно по-разному, поэтому тот факт, что индексатор делает то же самое, в конечном итоге не имеет значения.

Конечно, вы можете просто создать две перегрузки с конкретными типаминужно, но это означает, что некоторые надоедливые копирования и вставки.Любые попытки абстрагироваться от повторения во избежание повторения приведут к снижению производительности.

0 голосов
/ 14 января 2012

Вы можете сделать подпись вашего метода

public static int MyMethod<T> ( T[] arg1, T[] arg2 )

и используйте String.ToCharArray () перед передачей строковых аргументов (или, может быть, при перегрузке вы понимаете ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...