Avevo pensato che Generics in C# fosse implementato in modo tale che una nuova classe/metodo/what-have-tu sia stato generato, sia in fase di esecuzione che in fase di compilazione, quando è stato utilizzato un nuovo tipo generico, simile ai modelli C++ (che non ho mai esaminato e posso benissimo sbagliare, su cui accetterei volentieri la correzione).Come vengono implementati i C# Generics?
Ma nel mio codice mi si avvicinò con un controesempio precisa:
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();
}
}
}
Entrambe queste linee di console di stampa.
So che il vero motivo per cui questo accade è che la chiamata virtuale a Object.GetHashCode() non si risolve in Test.GetHashCode() perché il metodo in Test è contrassegnato come nuovo piuttosto che come override. Pertanto, so se ho usato "override" piuttosto che "new" su Test.GetHashCode(), quindi il ritorno di 0 avrebbe sostituito in modo polimorfico il metodo GetHashCode in oggetto e questo non sarebbe vero, ma secondo la mia (precedente) comprensione di generici C# non avrebbe avuto importanza perché ogni istanza di T sarebbe stata sostituita con Test, e quindi la chiamata al metodo avrebbe statisticamente (o con il tempo di risoluzione generico) risolta nel "nuovo" metodo.
Quindi la mia domanda è questa: Come vengono implementati i generici in C#? Non conosco il bytecode CIL, ma conosco il bytecode Java, quindi capisco come i linguaggi CLI orientati agli oggetti funzionino a un livello basso. Sentiti libero di spiegare a quel livello.
Per inciso, ho pensato che i generici C# fossero implementati in quel modo perché tutti chiamano sempre il sistema generico in C# "True Generics", rispetto al sistema di cancellazione del tipo di Java.
qualsiasi motivo per trasmettere all'oggetto qui 'gen == ((oggetto) testVar) .GetHashCode()'? – AlwaysAProgrammer
Anche se non risponde direttamente alla tua domanda, http://blogs.msdn.com/b/ericlippert/archive/2012/07/10/when-is-a-cast-not-a-cast.aspx ha alcune buone informazioni su come vengono espressi i farmaci generici e su come si relazionano tra loro in C#. – devstruck
@Yogendra Facendo questo accede al metodo Object.GetHashCode() piuttosto che al metodo "nuovo" Test.GetHashCode(). Ecco perché restituisce un valore diverso (perché esegue un metodo completamente diverso). – Carrotman42