No-parameter struct constructors & hiding virtual methods


1. Why do structs have a default no-parameter constructor that cannot be overridden What's the harm in overriding a struct's default constructor

2. Why would you want to hide a method by marking it "new" if it's been marked "virtual" in a base class Isn't the feature anti-OOP Why isn't NOT overriding a virtual method treated as a warning and not a lapse in judgement       


Answer this question

No-parameter struct constructors & hiding virtual methods

  • starkami

     Anachron wrote:
    "They don't allow you to define your own default constructor because they couldn't guarantee that it would be called in all situations."

    I don't understand that explanation. C# still allows you to define your default constructors for classes. C# cannot guarantee that the default constructor will get called for a class either.


    Yes it can - or rather, it guarantees that (except for a very few strange situations to do with serialization, IIRC) there will always be *a* constructor called before an instance of a class is created. However, with structs, there are times when you get a value of a struct but don't want to have the CLR calling a constructor. For instance:


    MyValueType[] foo = new MyValueType[10000];
     


    Should that call the no-arg constructor on all 10000 new instances How about an instance/class variable declaration with no initializer

    Jon



  • Bart Devriendt

    All the answers above are actually quite good. I'd like to add another reason related to assignment and efficiency.

    Consider the current no-arg constructor on structs. What does it do, exactly It creates a struct *value* initialized with zeros (or default values, to be precise). Then, when you have constructed it, how do you hold on to it Ultimately you need to assign it somewhere. This means copying it field by field into some variable of the same struct type.

    If you were allowed to write the constructor itself, presumably it would be to write particular values into the fields of the struct when you new() it. But then right after assigning these values to the new struct value, you would copy them all to the variable to which you assign the end result. Thus, you add an extra assignment of each field.

    If you want efficient but general code to initialize values of a particular struct type, one way to go about it is to write a method taking the struct as a ref parameter.

    I would like to add, that whenever you start thinking in terms of "constructing" your structs or "overriding" behavior this might be a hint that you should use objects instead. Objects are better for almost anything, and allocation and memory management really aren't that much of a deal efficiency-wise. Only for very high-performance situations structs are useful. There's very rarely, if ever, a functionality-based reason to pick structs over objects.

    In my opinion :-)

    Mads Torgersen



  • Naitsirhc4

    "They don't allow you to define your own default constructor because they couldn't guarantee that it would be called in all situations."

    I don't understand that explanation. C# still allows you to define your default constructors for classes. C# cannot guarantee that the default constructor will get called for a class either.

    Ignore my question about overriding constructors. Re-reading it, it doesn't make any sense. Big Smile

    Answer to #2 makes sense...

  • Giles Copnell

    >1. Why do structs have a default no-parameter constructor that cannot be overridden

    They don't allow you to define your own default constructor because they couldn't guarantee that it would be called in all situations.


    >What's the harm in overriding a struct's default constructor

    Constructors are never inherited and therefore never overridden.


    >2. Why would you want to hide a method by marking it "new" if it's been marked "virtual" in a base class

    You shouldn't use it to hide things. It's useful to make sure your code continues to compile without warnings with a changing base class.
     
    Imagine if you have a class Derived that derives from a class Base from a third party vendor. In your Derived class you add a method Foo. Now the third party vendor releases a new version of the library, and the Base class now also has a Foo method (same signature but does something completely different than your Foo or isn't virtual, so overriding it doesn't make sense). Then you can add the "new" keyword to your Foo method to explicitly state that this is a different Foo and make sure your existing code compiles and works.


    >Why isn't NOT overriding a virtual method treated as a warning and not a lapse in judgement

    Why would it be There's nothing wrong with not overriding a virtual method.



  • Savarage

    I'm going to escalate this to the C# team to see if they have any interesting answers. Will keep you posted...

    Jon



  • HalS

    I like to explain this distinction by looking at the implementation.

    All .NET variables are initialized either by setting all their bits to zero, or by simply moving the stack pointer and requiring an explicit initialization in the case of locals.

    The content of a class variable is a reference, so initializing its bits to zero gives you a null reference. That's a valid state, and no constructor got called. (This is why the "guarantee that a ctor gets called" statement seems wrong to me in this context -- the CLR actually does no such thing!)

    The content of a struct variable, however, is the sequence of its fields (plus some system-dependent padding). How does the CLR guarantee that a struct with all fields set to zero bits is in a valid state It does that by defining this state as the result of an imaginary default constructor for structs that does not actually exist.

    You are not allowed to define your own default ctor because you might set some bits to non-zero, and then the CLR could no longer create a valid struct instance just by setting all bits to zero!

    Now that's the explanation based on the current implementation of the CLR. I'm not sure there's an answer for the fundamental question, though -- why doesn't the CLR simply check whether a custom default ctor is defined, and call it accordingly Ten thousand times if necessary

    The only argument I see here is simplicity of implementation but maybe I'm missing some edge cases where checking for a default ctor would be really inconvenient or impossible.

  • No-parameter struct constructors & hiding virtual methods