Возьмите массив любого типа значения в качестве формального параметра - PullRequest
4 голосов
/ 18 февраля 2009

Я хотел бы иметь возможность объявить функцию как

void foo(<any value type>[] data){}

в C # 2.0. Если я объявлю это как

void foo(ValueType[] data){}

он компилируется, но тогда элементы в data [] обрабатываются так, как будто они получены из object, например Я не могу сказать что-то вроде

fixed (void* pData = data){}

Я бы хотел не принимать void * в качестве параметра - я просто хочу иметь возможность принимать любой массив значений и затем выполнять с ним неуправляемые действия.

ETA: с этой же проблемой связано:

public static unsafe void foo<T>(T[] data) where T:struct{
  fixed(void *p = data){}
}

на случай, если вам интересно. Исправлены ошибки, потому что он рассматривается как управляемый тип - CS0208, не может объявить указатель на управляемый тип. Смотрите «мм» ниже. Я думаю, что он прав ... это, вероятно, просто невозможно сделать.

Ответы [ 3 ]

3 голосов
/ 19 февраля 2009

Я не думаю, что это возможно с помощью 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 до тех пор, пока не будет завершена компиляция, поэтому сигнатура метода не будет совпадать.

0 голосов
/ 19 февраля 2009
public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
    foo(1, 2, 3, 4);
}

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

0 голосов
/ 19 февраля 2009

Это будет работать:

    public static void foo(System.Array data)
    {

    }

    static void Main(string[] args)
    {
        foo(new int[10]);  
    }

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

...