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 */ }

2,279 votes
Sign in
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Michael PatersonMichael Paterson shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →
    AnonymousAnonymous shared a merged idea: Add new constraint on type parameters in C#: where new(parameters)  ·   · 


    Sign in
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      • PhilippePhilippe 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 SolnikEyal 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.

      • sandorsandor 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 ShepherdTravis 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 SeemannMark 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

      • Eamon NerbonneEamon Nerbonne commented  ·   ·  Flag as inappropriate

        It would be much more useful it the constraints could be a little more general and not just for constructors. Operators spring to mind as being even more useful, and perhaps other static methods too.

      • Tom PottsTom Potts commented  ·   ·  Flag as inappropriate

        @giuseppe-lippolis I think you're confused; you can already do this with the current type system. Leaving your interface definition as it is, your class signature should be
        public class SelectableCollection<TItem, TValue> : ICollection<TItem> where TItem : ISelectableItem<TValue>

      • Brannon B. KingBrannon B. King commented  ·   ·  Flag as inappropriate

        I also would like a parent class on the numeric types that was usable. As an alternate, it might be nice to constrain types by operator availability.

        I also think we should fix the method resolution to use constraints as part of the method footprint. That way you could use generic type constraints on extension methods.

      • Giuseppe LippolisGiuseppe Lippolis commented  ·   ·  Flag as inappropriate

        another constraint interested to implement, it is a constraint that verifies if the generic type defined implements a specific generic Interface.

        public interface ISelectableItem <TValue>
        bool IsSelected {get; sets;}
        TValue Value {get; sets;}

        public class SelectableCollection <TItem>: ObeservableCollection <TItem>
        where TItem: ISelectableItem <?>
        public void SelectAll()
        foreach item in this
        item.IsSelected = true;

      • Marius GoppeltMarius Goppelt commented  ·   ·  Flag as inappropriate

        ... and please regard visibility. Currently, new constraint is always assumed as public. It suffices if the method which calls "Invoke" has sufficient access to the constructor. This is very useful for a factory pattern, where I don't want to expose the constructor.

        And don't forget VB.NET while you are at it! ;-)

      • CSharpJohnCSharpJohn commented  ·   ·  Flag as inappropriate

        @michael >> where T : int or long or float or double <<

        The issue is the lack of good generic math, specifically the lack of parent types or interfaces for int, long, float... like INumber, IInteger, IFloat.

        This said, I agree re; generic constraints
        ValueType does not cut it.

      • DavidDavid commented  ·   ·  Flag as inappropriate

        I like this. Here is yet another suggestion on the same line...
        as far as I'm aware, you can't do the following:

        public void DoSomething<T>() where T : Nullable
        public void DoSomething<T>() where T : NOT(Nullable)

        or somehow specify that T can (or cannot) be null. Recently I wanted to allow an "int?", or "long?" or "double?" (etc.) but not an "int", "long", or "double" but couldn't figure out how to do this. You CAN do this:

        public void DoSomething<T>() where T : class

        but that's not quite the same thing.

      • chhachha commented  ·   ·  Flag as inappropriate

        Yes, that's something I would also look forward to.

        Language: VB.NET

      ← Previous 1

      Feedback and Knowledge Base