Возьмите массив любого типа значения в качестве формального параметра.

StackOverflow https://stackoverflow.com/questions/561661

  •  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]);  
    }

Это не означает, что массив является массивом типов значений, но это будет работать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top