usando tipos tipo ser referencia genericos genericas debe colecciones clases c# .net generics operators on-the-fly

c# - tipos - Operador como y clases genéricas



tipos de genericos (4)

Estoy escribiendo el compilador .NET On-the-Fly para CLR scripting y quiero que el método de ejecución haga que el genérico sea aceptable:

object Execute() { return type.InvokeMember(..); } T Execute<T>() { return Execute() as T; /* doesn''t work: The type parameter ''T'' cannot be used with the ''as'' operator because it does not have a class type constraint nor a ''class'' constraint */ // also neither typeof(T) not T.GetType(), so on are possible return (T) Execute(); // ok }

Pero creo que el operador será muy útil: si el tipo de resultado no es T método devolverá null , ¡en lugar de una excepción! Es posible de hacer?


¿Hay alguna posibilidad de que Execute () devuelva un tipo de valor? Si es así, entonces necesitas el método de Earwicker para los tipos de clases y otro método genérico para los tipos de valores. Podría verse así:

Nullable<T> ExecuteForValueType<T> where T : struct

La lógica dentro de ese método diría

object rawResult = Execute();

Entonces, tendrías que obtener el tipo de rawResult y ver si se puede asignar a T:

Nullable<T> finalReturnValue = null; Type theType = rawResult.GetType(); Type tType = typeof(T); if(tType.IsAssignableFrom(theType)) { finalReturnValue = tType; } return finalReturnValue;

Finalmente, haga que su mensaje de ejecución original descubra qué T tiene (clase o tipo de estructura) y llame a la implementación adecuada.

Nota: Esto es de memoria aproximada. Hice esto hace aproximadamente un año y probablemente no recuerdo todos los detalles. Aún así, espero que apuntarlo en la dirección general ayude.


Necesitas agregar

where T : class

a su declaración de método, por ejemplo

T Execute<T>() where T : class {

Por cierto, como sugerencia, ese contenedor genérico realmente no agrega mucho valor. El que llama puede escribir:

MyClass c = whatever.Execute() as MyClass;

O si quieren tirar al fracaso:

MyClass c = (MyClass)whatever.Execute();

El método de envoltura genérica se ve así:

MyClass c = whatever.Execute<MyClass>();

Las tres versiones tienen que especificar exactamente las mismas tres entidades, solo en diferentes órdenes, por lo que ninguna es más simple o más conveniente, y sin embargo, la versión genérica oculta lo que está sucediendo, mientras que las versiones "crudas" dejan claro si habrá o no ser un lanzamiento o un null .

(Esto puede ser irrelevante para usted si su ejemplo se simplifica a partir de su código real).


No puede usar el operador as con un tipo genérico sin restricción. Como el operador as usa null para representar que no era del tipo, no puede usarlo en los tipos de valores. Si desea usar obj as T , T tendrá que ser un tipo de referencia.

T Execute<T>() where T : class { return Execute() as T; }


Parece que solo está agregando un método de envoltura para el tipo que desea el usuario, por lo tanto, solo agrega sobrecarga a la ejecución. Para el usuario, escribiendo

int result = Execute<int>();

no es muy diferente de

int result = (int)Execute();

Puede usar el modificador de salida para escribir el resultado en una variable en el alcance del llamante, y devolver un indicador booleano para decir si tuvo éxito:

bool Execute<T>(out T result) where T : class { result = Execute() as T; return result != null; }