I suggest you ...

Expand Generic Constraints for constructors

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

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

2,624 votes
Vote
Sign in
Check!
(thinking…)
Reset
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)  ·   · 

    28 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • user1jawuser1jaw 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 MarynowskiMike 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.

      • tsahitsahi 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 FaixJames 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 ØyvindPer Ø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 SmitJon 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)".

      • 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.
        example:

        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.

      ← Previous 1

      Feedback and Knowledge Base