Pensé que los genéricos en C# se implementaron de manera que se generara una nueva clase/método/lo que sea, en tiempo de ejecución o de compilación, cuando se usó un nuevo tipo genérico, similar a las plantillas de C++ (que en realidad nunca investigué y muy bien podría estar equivocado, sobre lo cual aceptaría con gusto la corrección).¿Cómo se implementan los C# Generics?
Pero en mi codificación me ocurrió con un contraejemplo exacta:
static class Program {
static void Main()
{
Test testVar = new Test();
GenericTest<Test> genericTest = new GenericTest<Test>();
int gen = genericTest.Get(testVar);
RegularTest regTest = new RegularTest();
int reg = regTest.Get(testVar);
if (gen == ((object)testVar).GetHashCode())
{
Console.WriteLine("Got Object's hashcode from GenericTest!");
}
if (reg == testVar.GetHashCode())
{
Console.WriteLine("Got Test's hashcode from RegularTest!");
}
}
class Test
{
public new int GetHashCode()
{
return 0;
}
}
class GenericTest<T>
{
public int Get(T obj)
{
return obj.GetHashCode();
}
}
class RegularTest
{
public int Get(Test obj)
{
return obj.GetHashCode();
}
}
}
estos dos líneas de consola de impresión.
Sé que la razón real de que esto ocurra es que la llamada virtual a Object.GetHashCode() no se resuelve en Test.GetHashCode() porque el método en Test está marcado como nuevo en lugar de sobrescribir. Por lo tanto, sé que si utilicé "anular" en lugar de "nuevo" en Test.GetHashCode() entonces el retorno de 0 anularía polimórficamente el método GetHashCode en el objeto y esto no sería cierto, pero de acuerdo con mi comprensión (previa) de los genéricos C# no habría importado porque cada instancia de T habría sido reemplazada por Prueba, y por lo tanto la llamada al método se habría resuelto de forma estática (o en el tiempo de resolución genérico) al "nuevo" método.
Así que mi pregunta es la siguiente: ¿Cómo se implementan los genéricos en C#? No conozco el bytecode de CIL, pero sí conozco el bytecode de Java, así que entiendo cómo funcionan los lenguajes CLI orientados a objetos en un nivel bajo. Siéntete libre de explicar en ese nivel.
Como nota aparte, pensé que los genéricos C# se implementaban de esa manera porque todos siempre llaman al sistema genérico en C# "Genéricos verdaderos", en comparación con el sistema de borrado de tipos de Java.
cualquier razón para convertir al objeto aquí 'gen == ((object) testVar) .GetHashCode()'? – AlwaysAProgrammer
Si bien no responde directamente su pregunta, http://blogs.msdn.com/b/ericlippert/archive/2012/07/10/when-is-a-cast-not-a-cast.aspx tiene algunos buenos información sobre cómo se emiten los genéricos y cómo se relacionan entre sí en C#. – devstruck
@Yogendra Al hacer esto accede al método Object.GetHashCode() en lugar del método "nuevo" Test.GetHashCode(). Es por eso que devuelve un valor diferente (porque ejecuta un método diferente por completo). – Carrotman42