I suggest you ...

Add support for ISupportInitialize on object initializers

Quite often, it's necessary to validate an object state when it's initialized. With constructor arguments, this is easy to do as it can be done at the end or begining of ctor code. With object initializers, it's nearly impossible, as there's no way to know programatically when the object initialization is finished.

There's a built-in mechamis for this that is being used in WinForms and WPF: the ISupportInitialize interface. The initialization code generated by both toolkits checks to determine if the object implements the interface. If it does, it will call BeginInit() before invoking all property setters, and EndInit() at the end. This provides a nice hook for validating all properties and maybe interrelated ones.

Adding this to the IL generated by the compiler for object initializers would make them inmensely more useful. I'd be willing to replace many ctor overloads with properties if I had that hook, given the much more readable code that results from using object initializers.

240 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…)
    kzukzu shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    5 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...
      • Renaud BancelRenaud Bancel commented  ·   ·  Flag as inappropriate

        It will be very nice to have automatic calls to BeginInit/EndInit in { } object initializer. I can't decide if an additional class attribute (AutoInitializeAttribute) is needed to allow the compiler to apply this behavior. It could be nice too to have an unified syntax for constructor parameters and member initializers. For example, AutoInitialize classes can allow to include constructor parameters in {} initializer block. The problem with this behavior is to define the rules to choose the correct constructor and to mix constructor parameters and member affectations. The great benefit is, more than a simple unified way to initialize object, a way to make refactoring easier. In particular if the developper give exactly the same name to constructor and public/internal/protected member fields/properties.

      • kzukzu commented  ·   ·  Flag as inappropriate

        @gagan syntax for object initializer is much nicer, and it looks consistently good even in the presence of nested object initialization. Optional parameters start looking quite ugly really soon.

        Also, with optional parameters you're essentially duplicating all your set-able properties instead of leveraging the equivalent language feature of object initializers: a waste of my (limited lifetime) keypresses ;).

        @gael: it works just fine for WPF and WinForms, and soon Json.NET (I hope, see http://json.codeplex.com/workitem/21269).

        .NET built-in serializers should also be updated to invoke the interface, of course, but as I use Json.NET almost exclusively, I don't care much ;).

        Construction via invoking the constructor and nothing else, would continue to work as usual. As the MSDN documentation says, it's an optional feature of the object. If mandatory, the object itself can validate that its BeginInit/EndInit pair has been called properly before doing any work (throw NotInitializedException or whatever). It's up to the implementer.

      • MuiBienCarlotaMuiBienCarlota commented  ·   ·  Flag as inappropriate

        MSDN ISupportInitialize documentation says;
        “Specifies that this object supports a simple, transacted notification for batch initialization.”
        and
        “ISupportInitialize allows controls to optimize multiple property assignments.”
        => Event if an object implement this interface, its use is not mandatory: it’s a way to permit optimization.

        If I am right, Daniel proposes to automatically generate a call to BeginInit at the begining of initialization block ({) and a call to EndInit at the end of this block if the object implements ISupportInitialize.

        Nothing prevents people from running these methods manually. Even after an initializer block, one can recall BeginInit follow by a EndInit (or BeginInit without a End, or a End without a begin, …). ISupportInitialize implementer must deals with it.

        @Gael:
        Ctor doesn’t know if it will be follow be a BeginInit. It has to do with it.

        In case of instance creation with Activator.CreateInstance, there’s no initialization Block but it’s possible to call Begin/Endinit manually.

        Serialization is a good place to generate BeginInit/EndInit calls to take advantage of optimizations.

      • Gael FraiteurGael Fraiteur commented  ·   ·  Flag as inappropriate

        The feature would be very useful, but it would be hard to get it right. Should EndInit be called when no field or property should be set? If not, how does a constructor know that it's going to be followed by BeginInit/EndInit? If yes, what happens if the object is instantiated dynamically (through Activator.CreateInstance, for instance)? How should the feature behave during deserialization (which can also be considered an initialization)?

      Feedback and Knowledge Base