如何在通用约束类中使用方法隐藏(新)
我有一个容器类,它具有受限于某些基类的泛型参数。提供给泛型的类型是基类约束的子类。子类使用方法隐藏(新)来改变方法从基类的行为(不,我不能让它变成虚拟的,因为它不是我的代码)。我的问题是'new'方法没有被调用,编译器似乎认为提供的类型是基类,而不是sub,就好像我已经把它转换为基类。如何在通用约束类中使用方法隐藏(新)
很明显,我误解了一些根本性的东西。我认为通用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();
}
}
}
编辑:
我想我的困惑来自于一个能做到这一点
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
方法隐藏是行不通的。我不得不说这些。
声明为new
的方法与基类中具有相同名称/签名的方法没有关系(从编译器的角度来看)。这只是编译器的方法,它允许您在派生类中定义不同的方法,这些方法与基类级联中的方法共享一个签名。
现在,就您的具体情况而言,请注意泛型必须编译为一组字节码,而不考虑通用参数提供的类型。因此,编译器只知道在泛型类型T上定义的方法和属性 - 这是您在泛型约束中指定的基类型。编译器对衍生类型中的new
方法一无所知,即使您创建了派生类型作为参数的泛型类型的实例。因此,泛型类中的调用将始终转到基类型的方法。
关于新/虚拟/覆盖有很多混淆;拿look at this SO question - 贾森和埃里克的回答非常好。 Jon Skeet's answer也可能帮助你理解为什么你的实现行为如此。
有你来解决此问题的两种可能的方式:
- 在泛型类执行条件铸(根据运行时类型信息),以派生类型(或接口)。这破坏了封装并增加了不希望的耦合。如果执行得不好,它也很脆弱。
- 定义您在通用约束中使用的接口,该接口公开您所关心的方法。如果你所得到的代码不是你可以改变的,这可能是不可能的。
谢谢,我想我现在明白了。 – ongle 2010-04-16 00:03:28
我认为this SO question我问了可能会帮助你。请看Jon Skeet在那里的答案,为什么这是不可能的。
是的,谢谢。我认为这是更多的运行时间,但我想我错了。 – ongle 2010-04-15 23:57:40
添加另一个图层 - 从您的第三方类继承您的泛型,而不是继承自第三方的新类。在这个新班级中,您可以将所讨论的方法定义为新的虚拟班级。如果所有的代码都不会直接引用第三方的类,它应该可以工作
谢谢,是的,我知道一些解决问题的方法。我只是想了解核心问题,所以我不会再犯这个错误。 – ongle 2010-04-16 00:01:32
可能的重复http://*.com/questions/774726/generics-accessing-new-members-not-hidden-members – 2010-04-15 22:59:38