Подтвердить что ты не робот

Использование ключевого слова "params" для общих параметров в С#

Сегодня я встретил красивый Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> делегат в С#.NET 4.5. Я предполагаю, что 16 было произвольным местом для остановки (какие методы имеют более 16 параметров?), Но это заставило меня задуматься: возможно ли в С# указать, что общий тип может иметь любое количество аргументов типа? аналогичным образом, что ключевое слово params для методов допускает любое количество аргументов для метода. Что-то вроде этого:

public class MyInfiniteGenericType<params T[]> { ... }

где внутри класса вы могли бы получить доступ к аргументам типа путем перечисления через них или с помощью T[index] таким же образом, что params допускает внутри методов.

У меня никогда не было пользы для этого лично, но делегат Func был бы идеальным местом для его использования. Не было бы необходимости в 16 различных типах Func!

Итак, мой вопрос: это можно сделать каким-либо образом в С#, а , если нет, это глупая идея?

4b9b3361

Ответ 1

возможно ли в С# указать, что общий тип может иметь любое количество аргументов типа?

Нет, у С# нет ничего подобного, я боюсь.

По существу Func<T> и Func<T1, T2> являются полностью несвязанными типами в отношении CLR, и нет ничего похожего на params для указания нескольких аргументов типа.

Что касается его полезности: я могу видеть случаи, когда это может быть полезно, но я подозреваю, что они достаточно редки, чтобы означать, что функция не пересекает порог "выгоды/стоимость". (Обратите внимание, что это почти наверняка потребует изменений CLR тоже.)

Ответ 2

В С++ 11 есть функция, о которой вы, по сути, говорите. Они называют это variadic templates.

Генераторы С# не совсем похожи на С++-шаблоны, и это затруднит создание совершенно той же вещи.

В случае С++ шаблоны расширяются во время компиляции в зависимости от того, какие конкретные типы используются. В случае с С# спецификация типа происходит полностью во время выполнения. И получившийся IL должен поддерживать число встречающихся типов.

Ответ 3

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

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

Ответ 4

Нет, это невозможно сделать.

Это не так просто, как рассматривать его как массив типов (понятие, которое даже не существует в С#). Рассмотрим Func - количество параметров типа должно быть таким же, как число параметров метода делегата Invoke. Но как программист мог бы выразить такую ​​связь между параметрами типа и регулярными параметрами?

Однако эта функция существует в С++ 11 - variadic templates. Обратите внимание, что С++ не позволяет получать доступ к параметрам отдельного типа с использованием синтаксиса массива - вместо этого функции обычно отделяют первый параметр типа от остальных и используют рекурсивные вызовы для распаковки остальных.

Ответ 5

Я просто обнаружил, что мне любопытно узнать, может ли кто-нибудь еще использовать это. Я написал общий композитор для создания композитов из миксинов, собранных с использованием функции Castle Dynamic Proxy.

Я построил композитор для поддержки двух микшинов и собирался продолжить "копирование и вставку и настройку (bleh)" двух композиторов mixin на еще 15 вариаций вплоть до 17 микширующего композитора (аналогично Func<T> через Func<T1...T16, T>). Но потом я подумал, не было бы здорово, если бы я мог просто определить Composer<TComposer, TIComposite, params[] TIMixin>!

К сожалению, я готов копировать и вставлять и корректировать (сама деятельность, которую генерируют нам не общие).