tipos interfaces implementacion genericos ejemplos declaracion c# .net generics clr

c# - interfaces - explícitamente emitidos parámetros de tipo genérico a cualquier interfaz



tipos de interfaces c# (2)

Creo que esto se debe a que el elenco de SomeClass puede significar cualquier cantidad de cosas dependiendo de las conversiones disponibles, mientras que el elenco a ISomeInterface solo puede ser una conversión de referencia o una conversión de boxeo.

Opciones:

  • Emitir al objeto primero:

    SomeClass obj2 = (SomeClass) (object) t;

  • Use as lugar:

    SomeClass obj2 = t as SomeClass;

Obviamente en el segundo caso también necesitaría realizar una verificación de nulidad después en caso de que t no sea SomeClass .

EDITAR: El razonamiento para esto se da en la sección 6.2.7 de la especificación C # 4:

Las reglas anteriores no permiten una conversión explícita directa de un parámetro de tipo no restringido a un tipo que no sea de interfaz, lo que podría ser sorprendente. El motivo de esta regla es evitar confusiones y dejar clara la semántica de tales conversiones. Por ejemplo, considere la siguiente declaración:

class X<T> { public static long F(T t) { return (long)t; // Error } }

Si se permitiera la conversión explícita directa de t a int, se podría esperar fácilmente que X<int>.F(7) devuelva 7L. Sin embargo, no lo haría, ya que las conversiones numéricas estándar solo se tienen en cuenta cuando se sabe que los tipos son numéricos en el momento de la vinculación. Para aclarar la semántica, el ejemplo anterior debe escribirse en su lugar:

class X<T> { public static long F(T t) { return (long)(object)t; // Ok, but will only work when T is long } }

Este código ahora se compilará pero ejecutando X<int>.F(7) arrojaría una excepción en el tiempo de ejecución, ya que un int encuadrado no se puede convertir directamente en un largo.

En Preguntas frecuentes sobre genéricos: Las mejores prácticas dice:

El compilador le permitirá emitir explícitamente parámetros de tipo genérico a cualquier interfaz, pero no a una clase:

interface ISomeInterface {...} class SomeClass {...} class MyClass<T> { void SomeMethod(T t) { ISomeInterface obj1 = (ISomeInterface)t;//Compiles SomeClass obj2 = (SomeClass)t; //Does not compile } }

Veo una limitación razonable tanto para las clases como para las interfaces, a menos que la clase / interfaz no se especifique como tipo de restricción.

Entonces, ¿por qué tal comportamiento, por qué está permitido para las interfaces?


En el principio de herencia de C #, las interfaces se pueden heredar varias veces, pero una clase solo una vez. Como la herencia de las interfaces tiene una jerarquía compleja, el framework .net no necesita asegurar el tipo genérico T una interfaz específica en el momento de la compilación. (EDIT) Por el contrario, una clase podría asegurarse una clase específica declarando una restricción de tipo en la compilación como el siguiente código.

class MyClass<T> where T : SomeClass { void SomeMethod(T t) { ISomeInterface obj1 = (ISomeInterface)t; SomeClass obj2 = (SomeClass)t; } }