通用转换类型不足以正确检索“新”属性

时间:2011-11-29 07:31:01

标签: c# generics casting

我有一个难以解决的泛型类型。

要进行单元测试,我有一个假的ScriptManager类型,类似于此定义:

public class FakeScriptManager : ScriptManager
{
   public new virtual bool IsNavigating { get; private set; }
}

我的测试方法如下:

    public string GetHistoryPoint<TScriptManager>(string key, TScriptManager scriptManager)
            where TScriptManager : ScriptManager
{
          TScriptManager realScriptManager = Convert.ChangeType(scriptManager, scriptManager.GetType());
          if (realScriptManager.IsNavigating)
          {
              // Do something
          }
}

测试方法如下:

using (FakeScriptManager scriptManager = new FakeScriptManager(true, false))
{
    object value = _handler.GetHistoryPoint(keyExists, scriptManager);
}

我打算为FakeScriptManager变量设置 NEW 属性 IsNavigating true 。但它无法做到。变量realScriptManager似乎无法从预期的通用TScriptManager类型中生成。

注意: 的 调试,尝试使用具体类型FakeScriptManager直接输入输入参数scriptManager,没关系。

所以,我的问题是:如何使通用类型的GetHistoryPoint方法正常工作? 请问有谁伸出援助之手吗?

1 个答案:

答案 0 :(得分:1)

几乎在所有情况下,方法隐藏(new)都是错误的做法;在几乎所有情况中,更好的方法是override。我的主要答案是:删除new

编译器正在做正确的事情;它只通过IsNavigating了解TScriptManager : ScriptManager,所以它使用那个就不足为奇了。 C#泛型不像C ++模板;他们可以使用类型的已知(where)结构中的多态性等,而只在名称的基础上寻找实际T的最佳拟合(鸭子) -typing)。

如果你真的需要这个,那么要么是反射,要么是4.0,dynamic(完全是鸭子型的):

dynamic obj = scriptManager;
if((bool)obj.IsNavigating) {
       ...
}

(注意上面的“显式接口实现”可能会失败,但这不是你正在做的事情)

此处的Convert.ChangeType没有任何用处。