У меня есть контейнерный класс, который имеет универсальный параметр, который ограничен некоторым базовым классом. Тип, предоставленный универсальному, является частью ограничения базового класса. Подкласс использует метод скрытия (новый), чтобы изменить поведение метода от базового класса (нет, я не могу сделать его виртуальным, поскольку это не мой код). Моя проблема в том, что «новые» методы не вызываются, кажется, что компилятор считает предоставленный тип базовым классом, а не подчиненным, как если бы я вывел его на базовый класс.
Очевидно, я здесь неправильно понимаю что-то фундаментальное. Я думал, что универсальный where T: xxx
был ограничением, а не типом upcast.
Этот пример кода в основном демонстрирует то, о чем я говорю.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericPartialTest
{
class ContextBase
{
public string GetValue()
{
return "I am Context Base: " + this.GetType().Name;
}
public string GetOtherValue()
{
return "I am Context Base: " + this.GetType().Name;
}
}
partial class ContextSub : ContextBase
{
public new string GetValue()
{
return "I am Context Sub: " + this.GetType().Name;
}
}
partial class ContextSub
{
public new string GetOtherValue()
{
return "I am Context Sub: " + this.GetType().Name;
}
}
class Container<T> where T: ContextBase, new()
{
private T _context = new T();
public string GetValue()
{
return this._context.GetValue();
}
public string GetOtherValue()
{
return this._context.GetOtherValue();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple");
ContextBase myBase = new ContextBase();
ContextSub mySub = new ContextSub();
Console.WriteLine(myBase.GetValue());
Console.WriteLine(myBase.GetOtherValue());
Console.WriteLine(mySub.GetValue());
Console.WriteLine(mySub.GetOtherValue());
Console.WriteLine("Generic Container");
Container<ContextBase> myContainerBase = new Container<ContextBase>();
Container<ContextSub> myContainerSub = new Container<ContextSub>();
Console.WriteLine(myContainerBase.GetValue());
Console.WriteLine(myContainerBase.GetOtherValue());
Console.WriteLine(myContainerSub.GetValue());
Console.WriteLine(myContainerSub.GetOtherValue());
Console.ReadKey();
}
}
}
Edit:
Полагаю, мое замешательство связано с тем, что это можно сделать
class SomeClass<T> where T: AnotherType, new()
{
T foo = new T();
}
И я ожидал, что T
будет T
, хотя я понимаю, что компилятор будет рассматривать T
как имеющий AnotherType
интерфейс. Я предполагал, что ввод T
произойдет во время выполнения, даже если интерфейс T
был установлен во время компиляции. Объявление T foo
кажется здесь вводящим в заблуждение, потому что оно действительно делает
AnotherType foo = new T();
Как только я понимаю, что на самом деле foo
не объявляется как тип T
, становится понятно, почему скрытие метода new
не будет работать.
И это все, что я должен сказать об этом.