Я думал, что Generics в С# были реализованы так, что новый класс/метод/what-have-you был сгенерирован либо во время выполнения, либо во время компиляции, когда использовался новый общий тип, аналогичный шаблонам С++ (который я никогда не рассматривал, и я очень хорошо мог ошибаться, о котором я с радостью принимаю исправление).
Но в моем кодировании я придумал точный контрпример:
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 hashcode from GenericTest!");
}
if (reg == testVar.GetHashCode())
{
Console.WriteLine("Got Test 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();
}
}
}
Печать обеих этих строк консоли.
Я знаю, что фактическая причина этого заключается в том, что виртуальный вызов Object.GetHashCode() не разрешен Test.GetHashCode(), потому что метод в тесте помечен как новый, а не переопределяющий. Поэтому я знаю, что если бы я использовал "переопределить", а не "новый" в Test.GetHashCode(), то возврат 0 мог бы полиморфно переопределить метод GetHashCode в объекте, и это было бы неверно, но в соответствии с моим (предыдущим) пониманием из генераторов С# это не имело бы значения, потому что каждый экземпляр T был бы заменен Test, и, таким образом, вызов метода был бы статически (или в течение общего времени разрешения) разрешен к "новому" методу.
Итак, мой вопрос таков: Как генерируются обобщения на С#? Я не знаю байт-код CIL, но я знаю байт-код Java, поэтому я понимаю, как объектно-ориентированные языки CLI работают на низком уровне уровень. Не стесняйтесь объяснять на этом уровне.
В стороне, я думал, что С# generics были реализованы таким образом, потому что каждый всегда вызывает общую систему в С# "True Generics" по сравнению с системой стирания типов Java.