为什么 C# 不接受带有泛型参数的构造函数要求?

发布于 2024-11-29 12:48:40 字数 332 浏览 0 评论 0原文

使用 C# 泛型,您可以拥有这样的类:

class Foo<T> where T:new() {}

这意味着类型 T 应该有一个不带参数的构造函数。 那就太好了?

class Foo<T> where T : new(string)
{
    private T CreateItem()
    {
        string s="";
        return new T(s);
    }
}

如果我们能够知道: Microsoft 有什么理由没有将此功能添加到该语言中,

Working with C# Generics you can have a class like this:

class Foo<T> where T:new() {}

Which means that the type T should have a constructor without parameters. It would be nice if we could have:

class Foo<T> where T : new(string)
{
    private T CreateItem()
    {
        string s="";
        return new T(s);
    }
}

Is there any reason that Microsoft haven't added this feature to the language?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

像你 2024-12-06 12:48:40

Microsoft 没有将此功能添加到该语言中是否有任何原因?

您描述的功能是更一般功能“允许需要特定方法存在的约束”的特定情况。例如,您可能会说:

void M<T>(T t) where T has an accessible method with signature double Foo(int)
{
    double x = t.Foo(123);
}

我们在 C# 中没有该功能,因为必须通过成本效益分析来证明功能的合理性。从设计和实现的角度来看,这将是一个相当昂贵的功能 - 该功能不仅会推动 C# 的需求,还会推动所有 .NET 语言的需求。证明该功能合理的引人注目的好处是什么?

此外:假设我们确实设计了该功能。 如何有效实施?泛型类型系统中的约束经过精心设计,以便抖动可以生成有效的代码一次,然后可以为每个引用类型共享。我们如何为任意方法模式匹配生成高效代码?当方法的槽在编译时已知时,这种高效的调度就非常简单;有了这个功能,我们将不再拥有这种优势。

您想要的功能是相同的功能,只是方法类型仅限于构造函数。

请记住,泛型的目的是让您编写泛型类型代码。如果您需要的约束比类型系统中可以捕获的内容更具体,那么您可能会尝试滥用泛型。

Is there any reason that Microsoft haven't added this feature to the language?

The feature you describe is a specific case of the of the more general feature "allow a constraint that requires a particular method to exist". For example, you might say:

void M<T>(T t) where T has an accessible method with signature double Foo(int)
{
    double x = t.Foo(123);
}

We don't have that feature in C# because features have to be justified by a cost-benefit analysis. That would be a pretty expensive feature from both a design and implementation point of view -- a feature that would drive requirements onto not just C# but every .NET language. What's the compelling benefit that justifies the feature?

Moreover: suppose we did design that feature. How would it be implemented efficiently? The constraints in the generic type system have been carefully designed so that the jitter can generate efficient code once that can then be shared for every reference type. How would we generate efficient code for arbitrary method pattern matching? That sort of efficient dispatch is pretty straightforward when the method's slot can be known at compile time; with this feature we would no longer have that advantage.

The feature you want is the same feature, just with the kind of method restricted to a constructor.

Remember, the purpose of generics is to let you write generically typed code. If you're requiring constraints that are more specific than things that can be captured in the type system then you might be trying to abuse generics.

痕至 2024-12-06 12:48:40

不要尝试猜测为什么 Microsoft 决定采用特定的实现,这里为您提供了一种解决方法,使用工厂模式

public interface IFactory<T>
{
   T CreateItem(string s);
}

class Foo<TFactory,T> where TFactory : IFactory<T>, new()
{
    private T CreateItem()
    {
        var factory = new TFactory();
        string s="";
        return factory.CreateItem(s);
    }
}

使用此模式,假设您有一个类 Bar,它有一个采用单个字符串的构造函数

public class Bar
{
   public Bar(string laa)
   {}
}

:只需要一个实现 IFactoryBarFactory

public class BarFactory : IFactory<Bar>
{
   public BarFactory () {}
   public Bar CreateItem(string s)
   {
      return new Bar(s);
   }
}

现在您可以将该工厂与 Foo 一起使用

var foo = new Foo<BarFactory,Bar>(); // calls to CreateItem() will construct a Bar

Rather than try to guess why Microsoft decided on a particular implementation, here's a workaround for you, using the factory pattern

public interface IFactory<T>
{
   T CreateItem(string s);
}

class Foo<TFactory,T> where TFactory : IFactory<T>, new()
{
    private T CreateItem()
    {
        var factory = new TFactory();
        string s="";
        return factory.CreateItem(s);
    }
}

Using this pattern, say you have a class Bar which has a constructor taking a single string:

public class Bar
{
   public Bar(string laa)
   {}
}

You just need a BarFactory which implements IFactory<Bar>

public class BarFactory : IFactory<Bar>
{
   public BarFactory () {}
   public Bar CreateItem(string s)
   {
      return new Bar(s);
   }
}

Now you can use that factory with Foo

var foo = new Foo<BarFactory,Bar>(); // calls to CreateItem() will construct a Bar
只等公子 2024-12-06 12:48:40

当我想要一个调用带有参数的构造函数的泛型函数时,我采用的解决方案是使用反射来查找和调用它。

鉴于我可以控制泛型以及它所实现的所有类(并且此函数是构造这些类的唯一位置),我认为我可能最好为这些类提供一个默认构造函数并添加一个 Initialize他们都实现了接口中的方法。

(允许向接口添加一般静态方法的解决方案将是理想的。)

The solution I adopted when I wanted a generic function that invoked a constructor with arguments was to use reflection to find and invoke it.

Given that I had control of both the generic, and all the classes it was implemented over (and this function was the only place those classes were constructed), I think I might have been better to give the classes a default constructor and added an Initialize method in the interface they all implemented.

(A solution that allowed adding static methods in general to an interface would be ideal.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文