2011-01-19 19 views

Respuesta

11

Le permite utilizar el operador as en T si es T:class.

Le prohíbe comparar T con null si T es T:struct.

Tenga en cuenta que si omite T:class, entonces puede comparar T a nulo, incluso cuando T es un tipo de valor.

[Nota: Necesitaba editar esta publicación varias veces antes de que fuera correcta. Al menos espero que ahora sea correcto.]

-1

"T: clase" forzará que el tipo genérico especificado sea una clase, no un valor. Por ejemplo, podemos compensar una clase ObjectList que requiere el tipo genérico especificado a ser una clase, no es un valor:

class ObjectList<T> where T : class { 
    ... 
} 

class SomeObject { ... } 

ObjectList<int> invalidList = new ObjectList<int>(); //compiler error 

ObjectList<SomeObject> someObjectList = new ObjectList<SomeObject>(); //this works 

Esto obliga a un invariante en su tipo T genérica que de otro modo podrían no ser ejecutable. "T: struct" funcionaría de la misma manera. Tenga en cuenta que también puede usar esta construcción para exigir no solo que el tipo T sea una clase, sino también que coincida con una interfaz. La muestra del código que tomé esto también tiene

class MyList<T> where T : class, IEntity { ... } 

que fuerza a T a ser una clase Y también ser un IEntity.

+0

Gracias , pero soy consciente de la semántica de las restricciones genéricas; lo que estoy pidiendo son ejemplos en los que las restricciones struct/class sean * useful *. – Oak

1

La principal utilidad que he encontrado en ella radica en la clasificación y fijación del objeto en la memoria.

Por ejemplo, hago un montón de trabajo con estructuras internas que no pueden ser auto-convertidos, o son enviados por el cable como un flujo de bytes, por lo que escribió este helper:

public static T PinAndCast<T>(this Array o) where T : struct 
{ 
    var handle = System.Runtime.InteropServices.GCHandle.Alloc(o, GCHandleType.Pinned); 
    T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
    handle.Free(); 
    return result; 
} 
+0

Pensé que crear nuevas instancias depende de las restricciones "T: new()", no de las restricciones de clase/estructura? Además, no estoy muy familiarizado con Marshalling y la fijación de memoria en C#, ¿podría proporcionar un ejemplo de código? – Oak

+0

Todo depende de los detalles específicos. En mi caso, he necesitado convertir un conjunto existente de bytes en una estructura. Sin embargo, la creación de nuevas instancias, específicamente, depende de la nueva() restricción. He editado mi respuesta para reflejar esto. –

Cuestiones relacionadas