2

不知道这个问题到底是关于什么的。

这是问题所在。假设,我正在开发一个框架,该框架将被打包到一个没有可用源代码的程序集中并作为产品交付。从一开始,框架的开发就考虑到了可扩展性,我的意思是一些目标域细节/数据/类将由引用框架的最终用户/程序集定义。启用它的一种方法是在框架中使用泛型,以便稍后定义所有内容。但是,一旦将泛型引入单个类,所有依赖/引用类和方法都必须使用所有确切的约束重新声明它。传递一个泛型并不是什么大问题,但是当你必须处理时,事情很快就会失控,比如处理其中的 8 个,这一点也不罕见。在框架中的每个小类中,您必须放置几行刚刚重新声明的类型参数,这些参数在所有类中都是相同的。似乎一个快速而肮脏的解决方案只是拥有某种类似 c++ 的宏,它将向所有(大多数)类添加相同的通用声明。但是 C# 没有宏,所以你必须手动完成。这是我们提出一个问题的地方:将这些参数从括号中取出并在程序集(项目)级别声明一次需要什么?这样您就不必编写“公共类实体* 但是 C# 没有宏,所以你必须手动完成。这是我们提出一个问题的地方:将这些参数从括号中取出并在程序集(项目)级别声明一次需要什么?这样您就不必编写“公共类实体* 但是 C# 没有宏,所以你必须手动完成。这是我们提出一个问题的地方:将这些参数从括号中取出并在程序集(项目)级别声明一次需要什么?这样您就不必编写“公共类实体*< TField> * { ... }",因为 TField 已定义,并且无论何时看到它,这意味着该类使用与程序集级别的声明相同的声明隐式知道它。通过链接此类通用程序集,开发人员必须在它们能够使用之前提供所有类型参数,或者如果某些参数仍然未绑定,则重新声明它们以供以后使用。

问题:

  • 你有没有遇到过这样的情况?
  • 您认为拥有此功能可能会有所帮助吗?
  • 如果是这样,您目前如何在没有人的情况下相处?
  • 对于那些从事 c# 工作的人:你们有什么机会将它添加到一些新版本的 c# 中?

谢谢!

更新:

我不想过多介绍细节,但按照你的意愿做了。很难做出一个很好的说明性例子,所以让我分享一下现有的情况。我正在研究一个文本处理框架,其中我有一个核心库来标记文本并具有所有可能的模式来匹配它。它不知道如何处理名词和动词等词性。幸运的是,还有另一个组件可以做到这一点。现在的目标是使用来自另一个库的词性知识来扩展核心库中的模式。我这样做的方法是向名为“CustomPattern”的核心库添加了一个特殊模式,该模式由任意类参数化,可以用任何东西替换。在我们的例子中,它是 PartOfSpeach 枚举。看看https://gist.github 上的代码段落。.

这里的问题是,如何避免在核心库中使用 TDetails 泛型,但又能够使用附加任意数据的自定义模式?

这里唯一的要求是我们必须保持代码的严格类型,就像现在一样

4

3 回答 3

4

我不喜欢您呈现的场景,但另一种选择是嵌套类型:

public sealed class Foo<T> where T : Whatever {
    public class Bar { ... }

    public interface IBlap { ... }
}

内部的每种类型Foo<T>都可以隐式访问,T而无需复制约束。出于代码管理的目的,可以将其拆分为多个文件,再次仅提及约束一次:

// file 1
partial class Foo<T> where T : IWhatever
{

}
// file 2
partial class Foo<T>
{
    public class Bar
    { ... }
}
// file 3
partial  class Foo<T>
{
    public interface IBlap
    { ... }
}

但首先:理智地检查你的场景。

于 2012-05-10T06:03:10.050 回答
4

你有没有遇到过这样的情况?

是的。

您认为拥有此功能可能会有所帮助吗?

我认为能够跨类定义/共享通用约束会很有用,尽管由于可能被滥用,我对任何“全局”都持谨慎态度。

如果是这样,您目前如何在没有人的情况下相处?

我发现我有过度使用泛型的倾向,而且——尽管它们很有用——它们并不是最适合每一项任务。

最近我承担了使我的一个框架库对 WCF 友好的任务。到我完成的时候,几乎所有的通用接口都被重新设计了,或者已经创建了一个非通用的等价物。这是由于需要简化我的界面以更好地作为操作合同和数据合同工作,但当我完成时,我得出结论认为设计更干净、更直观,我放弃的很少。

如果您评估您的设计,您可能会发现可以通过要求输入参数从基类型或接口继承来替换受严格约束的通用接口。

例如,如果类型参数 TField1 必须是 Foo 类型的可实例化类,为什么不直接将接口更改为 require Foo(或更可能是其子类)?

public void Act<TField> where TField : Foo, new() { }

变成

public void Act( Foo f ) { } 

或者

public void Act( IFoo f ){ }

如果类被设计为作用于输入对象,通常它必须对对象的成员和能力有一些了解。

例如,List<T>( T obj )实际上不需要对其他存储它的输入值做太多事情,但TransferMoneyFromAccount<TAccount>( TAccount obj )可能确实需要对输入数据做非常具体的事情。大概可以改成TransferMoneyFromAccount( IAccount obj )

对于您的库的使用者,我认为接口比泛型更优雅地执行合同的想法。

对于那些从事 c# 工作的人:你们有什么机会将它添加到一些新版本的 c# 中?

来自一个从事 c# 工作的人(Eric Lippert):

经常有人问我为什么编译器不实现这个特性或者那个特性,当然答案总是一样的:因为没有人实现它。功能一开始是未实现的,只有在人们努力实现它们时才会实现:不努力,就没有功能。

取自:http: //blogs.msdn.com/b/ericlippert/archive/2012/03/09/why-not-automatically-infer-constraints.aspx(巧合的是,一篇关于泛型类型约束的文章)

于 2012-05-10T05:41:37.217 回答
1

您的问题非常笼统(没有双关语),这意味着您将得到通用答案。

我开发了一些考虑到可扩展性的框架(查看我的个人资料)。而且我从来不需要使用泛型来实现这一点。恕我直言,泛型用于获得通用类的类型安全性。

接口应该用于设计可扩展性框架。

(如果我误解了,请更新您的 Q)

于 2012-05-10T05:59:06.727 回答