I suggest you ...

Expand Generic Constraints for constructors

Currently when declaring a generic constraint on a Type parameter
public void DoSomething<T>() where T : new() { /* do something */ }

You can't specify that T has a constructor with specific parameters:
public void DoSomething<T>() where T : new(string, int) { /* do something */ }

3,388 votes
Sign in
Password icon
Signed in as (Sign out)
You have left! (?) (thinking…)
Michael Paterson shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →


Sign in
Password icon
Signed in as (Sign out)
  • Anonymous Wolf commented  ·   ·  Flag as inappropriate

    I see the point in removing the "new" constraint in favor of declaring static methods in interfaces. But as long as we have constructors the way we have them, it seems to be more consistent to have "new" constraints, and of course to extend them to typed ones.

    While we're at it: I'd prefer to replace

    T var = new T(args)


    T var = T.Create(args)

    In this form, enabling static members in interfaces would be the consistent thing to do.


    And/or, we could give interfaces the ability to declare constructors.

  • MouseCoder commented  ·   ·  Flag as inappropriate

    @"Anonymous": What you are doing is spam. Your repeated copy-and-paste (yes, I've seen the same comments in more than one thread) not only contributes nothing to the discussion, it is off-topic.

    With a major revision about every two years, .Net is developing at a rapid pace. No, it's not perfect, but then, neither is Java. If I decided to spam Java's boards about its imperfections that would not be helpful, either, and would do little other than stir up bad feelings between proponents of the languages.

  • Martijn Hoekstra commented  ·   ·  Flag as inappropriate

    It possible to work around this by passing the "creator function":

    public void DoSomething<T>(Func<string, int, T> creator) {
    var myt = creator("wizzle", 42)
    /* do something with myt */

    calling it with something like

    DoSomething((string str, int i) => new MyT(str, i))

  • Skye commented  ·   ·  Flag as inappropriate

    anybody who supports this point considers generic constaints is fixed after generic constranits published.

  • Just Nothing commented  ·   ·  Flag as inappropriate

    For the Anonymous guy (a big fan of Java and an anti fan of .NET) below me: You should understand that .NET was developed after Java, has something similar BUT not a copy (so that you said 'follow rather than lead'). Java syntax is one of the most annoying things I had to accept, too verbose and one of the most exemplary bad designs. At the time of approaching both .NET (C#) and Java, .NET had been much far better than Java in how easy we code and feel about coding. So I decided to code in .NET not Java - after that I'm not so sure how Java could become better? Maybe by imitating some features of .NET (more specifically of C# language)? Finally I read some article about the successor of Java and they call it SCALA, yes looks like Java won't be gone away but will be covered by that name, SCALA. Switch immediately to that instead if you don't like .NET, it may be the next world of Java developers, where you can be lifted to a higher level, at least feasible and more practical enough to be compared with .NET and C#.

  • Anonymous commented  ·   ·  Flag as inappropriate

    A lot of .NET guys are feeling abandoned out there today. They see the excitement around cross-platform, or mobile devices, or the cloud.

    .Net is the wrong product at the wrong time. That's what happens when you follow rather than lead. Microsoft's Java clone could never hope to be as successful as Java itself.

  • user1jaw commented  ·   ·  Flag as inappropriate

    Indeed, even better would be to extend this functionality not only to constructors, but other methods (e. g. Add(T) etc. ). This would give us an option to use real duck typing in C#. Quite a few features of C# work using duck typing (e. g. foreach, collection initializers, LINQ, await and tuple deconstruction in C#7). Would be nice if our classes could use it too!

  • Mike Marynowski commented  ·   ·  Flag as inappropriate

    @tsahi @david - It's perfectly possible to constrain to nullables, it just works a little backwards:

    public T? AddNullables<T>(T? v1, T? v2) where T : struct

    You constrain on the value type generic argument.

  • tsahi commented  ·   ·  Flag as inappropriate

    @UlrichBu: in my understanding, the purpose of the 'where' constraint is to give the compiler (and intellisense) information that will otherwise only be known at runtime, when an actual call to the method is made, and the concrete type, with its methods and constructor, is known. How does that serve this purpose?

    @David, I think that's exactly the same.

  • James Faix commented  ·   ·  Flag as inappropriate

    I think this would be better solved with static interfaces, then the static interface could have a constructor member, and the traditional constraint syntax 'where T : Interface' could be used. It would also provide an alternative to the existing 'where T: new()' syntax, which is essentially defining an anonymous static interface.

  • Per Øyvind commented  ·   ·  Flag as inappropriate

    I support this idea, since this will help with compile time checking of constructor arguments.
    One example of where this could be useful is for any algorithms that would require a Keyed hash algorithm where the point of the algorithm would be to initialize with a password.
    To make it less cluttered, and to pass the meaning, one should at least allow naming of the parameters or add a way to require implementers of a specific class or interface to provide a constructor with said arguments. and to only allow referencing the empty constructor or one of the required constructors.

  • Jon Smit commented  ·   ·  Flag as inappropriate

    I used to support this idea, but after seeing code in another language that was difficult to edit because it had this, I no longer support this idea. A solution most of the time is to pass in a extra argument for construction the object T, for example "public void DoSomething<T>(Func<string, int, T> Constructor)".

  • Philippe commented  ·   ·  Flag as inappropriate

    Although in general, I would recommend to add a parameter of type Func<string, int, T> for creation, it won't hurt if Generics would be made more flexible.

    They are quite limited compared to say C++ templates and even compared to new Apple Swift language.

  • Anonymous commented  ·   ·  Flag as inappropriate

    I do not think that this is a good idea. Although I already had similar problems it is only the tip of the iceberg.

    A constructor is basically a factory method. A factory method embedded in the class itself is usually a static method that returns a new object of the certain type.

    So the basic idea is the need for static methods that are provided by a generic type. This likely ends up with the request for static interface methods. See also http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2268973-virtual-static-method-in-interfaces-generics
    This would provide a solution not only for factory functions like the constructor.

    Unfortunately while the latter looks quite clear from the syntax point of view the implementation is not that easy. The runtime has to invoke different methods for different types but it cannot simply use callvirt as for normal interface methods. So there has to be a static dispatch table for each type (not instance) to call the methods without reflection.

  • Anonymous commented  ·   ·  Flag as inappropriate

    Relate would be "virtual static" functions.
    Absolutely useless until you consider generic functions.
    consider the following where F is a virtual static function that has
    been overridden.

    ***** void DoSomething<T>() where T: class A { T.F(); }

  • Eyal Solnik commented  ·   ·  Flag as inappropriate

    @Mark Seemann, I'd argue that coupling has to happen somewhere! and it's actually a job of the developer to decide where it happens.

    It's funny how some developers think sometimes, soon developers will think that their objects need to float in the air and have zero coupling which obviously promotes something else, abstractions and complexity.

    p.s. I understand the rational but I hate it when people just trash principles and make many of them an anti-pattern without a real world context WHEN it's actually can be useful to solve a problem, in fact, many anti-patterns might be considered as such because developers tend to abuse and overuse principles and think that there's a silver bullet to all problems.

    Soon we won't have any principles because all of them will be considered an anti-pattern.

  • sandor commented  ·   ·  Flag as inappropriate

    I'm disappointed Mark does not expand his point of view and tries to sell his book instead. Anyway it looks like his comment is based on dependency injection / IOC. But dependency injection is not for every classes and every in every scenario.

    The parameterless constructor constraint was an obvious need to avoid relying on reflection when building new instances. The same goes for this proposition. I don't think we want to rely on a IOC container to construct everyone of our types. And this suggestion is not bound/limited to IOC/DI.

    Adding that kind of feature would allow more scenarios. (I know we can currently circumvent this with an interface constraint and an Initialize(parameters) method).

  • Travis Shepherd commented  ·   ·  Flag as inappropriate

    When I run into this, it is usually because I want something like this to work:

    public class MyClass<T, U> where T : new(U)

    allowing me to construct a T that accepts a U in its constructor.

  • Mark Seemann commented  ·   ·  Flag as inappropriate

    FWIW, I think this isn't a good idea, because it leads to increased coupling.

    While you could argue that it would only make sense, since C# already has the 'where T : new()' constraint, I would rather argue that the 'new()' constraint never should have been added in the first place. However, now it's too late to remove it, but there's no reason to make things worse.

    For more details, see the section about the Constrained Construction anti-pattern in my book: http://amzn.to/12p90MG

← Previous 1

Feedback and Knowledge Base