Если аргумент общего типа (как вызывающего класса, так и метода вызова) ограничен where T : Base
, новый метод в T == Derived не вызывается, а вызывается метод в Base.C# & generics - почему метод в базовом классе называется вместо нового метода в производном классе?
Почему тип T игнорируется при вызове метода, хотя он должен быть известен до запуска?
Обновление: НО, когда ограничение использует интерфейс, как where T : IBase
метод в базовом классе вызывается (не метод в интерфейсе, который также невозможно).
Таким образом, система действительно способна обнаруживать типы, которые находятся далеко и выходит за пределы ограничения типа! Тогда почему он не выходит за пределы ограничения типа в случае ограничения типа класса?
Означает ли это, что метод в классе Base, реализующий интерфейс, имеет неявное ключевое слово переопределения для метода?
код теста:
public interface IBase
{
void Method();
}
public class Base : IBase
{
public void Method()
{
}
}
public class Derived : Base
{
public int i = 0;
public new void Method()
{
i++;
}
}
public class Generic<T>
where T : Base
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class GenericWithInterfaceConstraint<T>
where T : IBase
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class NonGeneric
{
public void CallMethod(Derived obj)
{
obj.Method(); //calls Derived.Method()
}
public void CallMethod2<T>(T obj)
where T : Base
{
obj.Method(); //calls Base.Method()
}
public void CallMethod3<T>(T obj)
where T : IBase
{
obj.Method(); //calls Base.Method()
}
}
public class NewMethod
{
unsafe static void Main(string[] args)
{
Generic<Derived> genericObj = new Generic<Derived>();
GenericWithInterfaceConstraint<Derived> genericObj2 = new GenericWithInterfaceConstraint<Derived>();
NonGeneric nonGenericObj = new NonGeneric();
Derived obj = new Derived();
genericObj.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod(obj); //calls Derived.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod3(obj); //calls Base.Method()
Console.WriteLine(obj.i);
obj.Method(); //calls Derived.Method()
Console.WriteLine(obj.i);
}
}
Выход:
0
0
0
0
1
1
1
2
Что заставляет вас думать, что интерфейс с ограничениями не вызывает 'IBase.Method'? Попробуйте выполнить литье 'Obj' на' IBase' и вызывать 'Method'. – supercat
Обратите внимание, что это имеет значение, если вместо этого вы пишете 'public class Derived: Base, IBase', т. Е. Повторите интерфейс в объявлении производного класса. Это называется повторной реализацией интерфейса *. [См. Спецификацию] (https://msdn.microsoft.com/en-us/library/aa664594.aspx). –