Domanda

Mi piacerebbe poter dichiarare una funzione come

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

in C# 2.0.Se lo dichiaro come

void foo(ValueType[] data){}

viene compilato, ma poi gli elementi in data[] vengono trattati come se derivassero da object, per esempio.Non posso dire qualcosa del genere

fixed (void* pData = data){}

Vorrei evitare di prendere void* come parametro: voglio solo essere in grado di accettare qualsiasi array di tipo valore e quindi eseguire operazioni non gestite su di esso.

ETA:Inoltre, questo ha lo stesso problema:

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

nel caso te lo stessi chiedendo.Risolto il problema con gli errori perché viene trattato come un tipo gestito: CS0208 non può dichiarare un puntatore a un tipo gestito.Vedere "mm" di seguito.Penso che abbia ragione...probabilmente semplicemente non è possibile farlo.

È stato utile?

Soluzione

Non penso che questo sia possibile usando C#.Le strutture non ereditano (anche se in modo approssimativo) da System.ValueType fino a dopo la fase di compilazione, quindi non è possibile abbinare la firma del metodo di Foo tramite polimorfismo.Anche i generici sono disponibili in base alle specifiche della lingua:

"Un tipo non gestito è qualsiasi tipo che non sia un tipo di riferimento, a parametro-tipo, o un tipo struct generico e non contiene campi il cui tipo non sia un tipo non gestito."

Ecco perché non puoi prendere l'indirizzo di T[] indipendentemente dal vincolo della struttura.

Potresti dichiarare un tipo struct (ad esempio Bar) come argomento di Foo, compilare il codice e modificare la firma del metodo a livello IL:

.method private hidebysig static void Foo(valuetype [mscorlib]System.ValueType[] args) cil managed

E poi anche la chiamata:

IL_0020: call void ConsoleApplication1.Program::Foo(valuetype [mscorlib]System.ValueType[])

Anche se sono riuscito a eseguire il programma risultante, non so che tipo di effetti collaterali abbia.Inoltre, anche se potessi fare riferimento alla funzione modificata, non saresti in grado di chiamarla da C# perché ancora una volta le strutture non ereditano da System.ValueType fino a dopo la compilazione, quindi la firma del metodo non corrisponderebbe.

Altri suggerimenti

public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
    foo(1, 2, 3, 4);
}

Non dovresti inserire il parametro generico perché il compilatore rileverà il tipo dal primo parametro di foo.

Funzionerebbe:

    public static void foo(System.Array data)
    {

    }

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

Non impone che l'array sia un array di tipi di valore, ma funzionerebbe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top