【问题标题】:Can you restrict the type of Type in a generic?你能在泛型中限制类型的类型吗?
【发布时间】:2017-05-19 14:29:42
【问题描述】:

我有一本字典,其中键和值都是Type 类型,就像这样...

private static Dictionary<Type, Type> myDict;

我要做的是将第二个 Type 限制为仅是从 FrameworkElement 继承的类型。

请注意,我不是在讲述 FrameworkElement 实例,我只是尝试存储从 FrameworkElement 派生的 Type 类型的对象,从而使以下陈述为真...

var isTypeStorable = typeof(FrameworkElement).IsAssignableFrom(FooType);

这样可以吗?

顺便说一句,是的,我知道我可以在添加到字典之前使用上述内容进行运行时检查(这就是我现在正在做的事情)。我想知道该语言中是否有任何功能可以让我在编译时限制它。

【问题讨论】:

  • AFAIK 不,没有。您可以创建一个专门的字典,覆盖AddAddRange 方法,如果输入错误则抛出,但这仍然只提供运行时错误检查。我几乎想知道是否有更好的方法来实现你的最终目标,也许使用工厂或某种 DI?您能详细说明一下字典是如何使用的吗?
  • 这正是我目前正在做的事情。这更像是对作为语言特征的一般概念/能力的疑惑。
  • 通用约束没有帮助?类似于T : FrameworkElement
  • @MrinalKamboj 没有T。我们正在这里处理Type 的实例。
  • @MrinalKamboj,换句话说,它是T : Type,但我正试图进一步将其限制为特定类型。

标签: c# generics type-conversion


【解决方案1】:

,这是不可能的。 FrameworkElement.GetType()FooType 在类型系统中没有关系,两者都只是 Types。如果你想限制你的泛型,你将不得不通过运行时检查和异常来做到这一点,泛型约束在这里对你没有帮助。

如果您知道要在编译时存储什么(或者对一些复杂的反射感到满意),您可以将 API 更改为不采用 Type,而是使用泛型:

public void AddTypeForType(Type x, Type y)

可以替换为

public void AddTypeForType<T1, T2>() where T1 : FrameworkElement
{
    myDict.Add(typeof(T1), typeof(T2));
}

你可以这样称呼它:

AddTypeForType<FrameworkDerivedClass, MyCustomClass>();

但这更多的是 API 更改,而不是您问题的答案。

【讨论】:

  • 不知道你的第二个例子是什么意思。您已经指定了两个没有在签名中使用的泛型类型。甚至不确定会编译。另外,T1 被限制为 FrameworkElement instance 而不是 Type。我试图将其限制为一个 Type 对象,该对象要么是 FrameworkElement 类型,要么派生自 FrameworkElement 类型。
  • @MarqueIV 添加了调用它的示例。正如我所说,这是一种接近于您想要的 API 的更改,但是如果您在编译时不知道实际类型,则以调用超级复杂为代价。
  • 有趣的方法!但是现在你将如何在运行时使用 Type 类型的变量来调用它? ...或者您是否会使用常规的 Add 方法进行手动检查?
  • @MarqueIV 如果您只在运行时知道您的类型,您将需要大约 10 行反射来调用该方法。 真的丑。或者,您将需要在正常方法中使用 if/exception 进行正常运行时类型检查,因为您可能已经拥有了。这就是为什么我的回答说“不”:)
  • 好吧,我将你的标记为创造性地使用这样的泛型的答案,尽管我希望这是不可能的。真可惜……在其他语言中是可能的。呃,好吧! :)
【解决方案2】:

我认为没有这样的,但是您可以通过在添加到字典之前检查项目来实现这一点,我的意思是这样的:

Xx,Yy 成为我想添加到myDict 的项目所以我可以做的是,首先检查键是否存在,然后检查值的条件(inherit from FrameworkElement.

if(!myDict.ContainsKey(Xx) && /* Yy is inherited from FrameworkElement */)
{
   myDict.Add(Xx,Yy);
}

【讨论】:

  • 是的,这就是我对“isTypeStorable”标志所做的事情。只是想知道我是否可以在编译时而不是运行时得到这个。
  • @MarqueIV 如果我有myDict.Add(CallExternalFunction(), CallExternalFunction()) 怎么办?编译器如何知道CallExternalFunction() 的返回类型而不在编译时运行函数?除非您切换到泛型并使用 nvoigt 的示例,否则无法在编译时完成。
  • 这不太正确。 Add 方法是类型化的,意思是如果这些函数没有正确的返回类型,编译器会捕获它。
猜你喜欢
  • 2011-10-16
  • 2020-08-25
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-17
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多