Возьмите массив любого типа значения в качестве формального параметра.
-
05-09-2019 - |
Вопрос
Я хотел бы иметь возможность объявить функцию как
void foo(<any value type>[] data){}
в С# 2.0.Если я объявлю это как
void foo(ValueType[] data){}
он компилируется, но затем элементы в data[] обрабатываются так, как будто они получены из object
, напримерЯ не могу сказать что-то вроде
fixed (void* pData = data){}
Я бы не хотел использовать void* в качестве параметра — я просто хочу иметь возможность принимать любой массив типов значений, а затем выполнять с ним неуправляемые действия.
Расчетное время прибытия:Кроме того, есть та же проблема:
public static unsafe void foo<T>(T[] data) where T:struct{
fixed(void *p = data){}
}
на случай, если вам интересно.Исправлена ошибка, поскольку он рассматривается как управляемый тип — CS0208, не может объявить указатель на управляемый тип.См. «мм» ниже.Я думаю, он прав...вероятно, это просто невозможно сделать.
Решение
Я не думаю, что это возможно с использованием C#.Структуры не наследуются (хотя и слабо) от System.ValueType до момента компиляции, поэтому вы не можете сопоставить сигнатуру метода Foo с помощью полиморфизма.Обобщения также доступны в соответствии со спецификацией языка:
«Неуправляемый тип — это любой тип, который не является ссылочным типом, тип-параметр, или общий тип структуры и не содержит полей, тип которого не является неуправляемым типом ».
Вот почему вы не можете взять адрес T[] независимо от ограничения структуры.
Вы можете объявить тип структуры (скажем, Bar) в качестве аргумента Foo, скомпилировать код и изменить сигнатуру метода на уровне IL:
.method private hidebysig static void Foo(valuetype [mscorlib]System.ValueType[] args) cil managed
И еще звонок:
IL_0020: call void ConsoleApplication1.Program::Foo(valuetype [mscorlib]System.ValueType[])
Хотя мне удалось запустить получившуюся программу, я не знаю, какие у нее побочные эффекты.Кроме того, даже если бы вы могли ссылаться на измененную функцию, вы не смогли бы вызвать ее из C#, поскольку структуры снова не наследуются от System.ValueType до момента компиляции, поэтому сигнатура метода не будет совпадать.
Другие советы
public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
foo(1, 2, 3, 4);
}
Вам не нужно вводить общий параметр, поскольку компилятор определит тип из первого параметра foo.
Это будет работать:
public static void foo(System.Array data)
{
}
static void Main(string[] args)
{
foo(new int[10]);
}
Это не означает, что массив является массивом типов значений, но это будет работать.