Sign in to follow this  

[C#] Is it possible to override the default constructor for a struct?

This topic is 2852 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

If I have a struct:
    public struct Contact2D
    {
        public RigidBody2D[] body;              // Two rigid bodies involved in the collision pair
        public bool closestOnly;                // Only keep the closest shape intersected?
        public Vector2[] point;                 // Contact points for the two shapes involved in collision pair
        public Vector2 normal;                  // Contact normal
        public float penetration;               // Penetration depth (at the contact point)       
        public float t0;                        // Time of first collision (point of entry)
        public float t1;                        // Time of last collision (point of exit)

        float min;                              // Minimum recorded distance for this contact
        float max;                              // Maximum recorded distance for this contact

        public Contact2D(bool closestOnly)
        {
            body = new RigidBody2D[2];
            this.closestOnly = closestOnly;
            point = new Vector2[2];
            normal = Vector2.Zero;
            penetration = 0.0f;
            t0 = float.MinValue;
            t1 = float.MaxValue;
            
            // Reset min/max value for each new contact [Don't use static variable]
            min = float.MaxValue;
            max = float.MinValue;
        }


Is it possible to override the default constructor that creates a new Contact2D but with the bool closestOnly set to true? Therefore: Contact2D contact = new Contact2D() would initialise all the parameters as the Contact2D(bool closestOnly) constructor would, but the closestOnly bool would automatically be set to true? Thanks

Share this post


Link to post
Share on other sites
Don't know about c# in such a case but I would think that you only have to write the constructor yourself with just initializing the attributes you want and leave the remaining untouched. This should pretty much be the same as the default constructor would do.

Share this post


Link to post
Share on other sites
Quote:
Original post by Waterwalker
Don't know about c# in such a case but I would think that you only have to write the constructor yourself with just initializing the attributes you want and leave the remaining untouched. This should pretty much be the same as the default constructor would do.


C# doesn't seem to allow this:

"Structs cannot contain explicit parameterless constructors"

Share this post


Link to post
Share on other sites
Quote:
Original post by Spa8nky
If I have a struct:

*** Source Snippet Removed ***

Is it possible to override the default constructor that creates a new Contact2D but with the bool closestOnly set to true?

You can give explicit values to members:

public struct Contact2D
{
public RigidBody2D[] body; // Two rigid bodies involved in the collision pair
public bool closestOnly = true; // Only keep the closest shape intersected?
public Vector2[] point = new Vector2[2]; // Contact points for the two shapes involved in collision pair
public Vector2 normal; // Contact normal
public float penetration; // Penetration depth (at the contact point)
public float t0 = 42.0f; // Time of first collision (point of entry)
public float t1; // Time of last collision (point of exit)

float min; // Minimum recorded distance for this contact
float max; // Maximum recorded distance for this contact

}



The values are set when the instance is created.

Share this post


Link to post
Share on other sites
It's not possible with a struct.

This is due to the nature of structs, in that they are value types rather than reference types.

What is wrong with Contact2D c2 = new Contact2D(true); anyway?

Share this post


Link to post
Share on other sites
No, structs cannot have either initializers for instance fields nor explicit parameter-less constructors. This stems from their nature as value types, which means that the runtime will default initialize a struct to all zeroes.

You can accomplish what you want by using a static construction method:

public static Contact2D ClosestContact()
{
return new Contact2D(true);
}



Looking at the current constructor though, I would say that your class might not be a good candidate for a value type, since many of the members need some sort of initial value other than the default.

Share this post


Link to post
Share on other sites
I don't understand why C# prohibits this. What would break if they allowed you to specify what the 'real' defaults of a struct are, as opposed to assuming that it should always be the default(Type) result?

Admittedly I've never come across a situation where I've needed to - I use classes most of the time - but I've still never read anything which properly explains why it's not allowed.

Hopefully someone can enlighten me?

Share this post


Link to post
Share on other sites
Quote:
Original post by Barguast
I don't understand why C# prohibits this. What would break if they allowed you to specify what the 'real' defaults of a struct are, as opposed to assuming that it should always be the default(Type) result?

Admittedly I've never come across a situation where I've needed to - I use classes most of the time - but I've still never read anything which properly explains why it's not allowed.

Hopefully someone can enlighten me?


From what I understand it's an optimization. Structs map easily to blocks of bits. It's relatively quick to simply zero out the block and be good to go.

Share this post


Link to post
Share on other sites
An enforced optimisation? Seems a very odd thing to do. If that were the case, then why not allow people to override the default constructor and simply not use the optimisation in that situation (perhaps discourage its use, if necessary).

I didn't think initialisation of a C# / managed struct would be as simple as zero-ing memory (a-la plain old C) anyway.

Share this post


Link to post
Share on other sites

namespace TestApp
{
public struct Foo
{
public int Bar;
}

public class Baz
{
public int Bat;
}

class Program
{
static void Main(string[] args)
{
Foo bar;
Baz bat;

bar.Bar = 5;
bat.Bat = 5;
}
}
}



Try to use the above example in Visual Studio. Notice that "bat.Bat" is an illegal operation, because the object "bat" has not been constructed. However, "bar.Bar" is legal. This is because C# requires that value types must be initialized the moment they are declared. This is a consequence of the stance the originators of C# have taken on the definition of reference types versus value types in the language. Preventing default construction is just a strict enforcement of the policy that must fully define a struct at initialization (hence why you can provide parameterized constructors, but only if every member data field of the struct is assigned inside of each constructor).

If you notice, you can change the IL to allow for default construction, and it is not prevented by the CLR, so other languages can allow it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Barguast
An enforced optimisation? Seems a very odd thing to do. If that were the case, then why not allow people to override the default constructor and simply not use the optimisation in that situation (perhaps discourage its use, if necessary).

I didn't think initialisation of a C# / managed struct would be as simple as zero-ing memory (a-la plain old C) anyway.


It's got to be implemented somewhere. Under the hood, there's still bits. Especially for small oft-copied objects (read: structs) even the conditional might be a fair increment to init time.

Part of the practical features that got C# adopted in the first place was a reasonably good performance profile compared to its peers. Creating/copying primitives is a bigger piece of that pie than it might first appear.

Share this post


Link to post
Share on other sites
Yes, but I would have thought the language could support speedy conventional structs (as they are now) and fallback to an implementation that allows custom defaults for when needed.

Share this post


Link to post
Share on other sites
Quote:
Original post by Barguast
Yes, but I would have thought the language could support speedy conventional structs (as they are now) and fallback to an implementation that allows custom defaults for when needed.


It is an intentional design philosophy limitation, not a CLR limitation. The C# development team wanted the language to enforce certain paradigms, with this being one.

Share this post


Link to post
Share on other sites
Quote:

Yes, but I would have thought the language could support speedy conventional structs (as they are now) and fallback to an implementation that allows custom defaults for when needed.

C# does not dictate this behavior, the CLR does. The CLR will zero-initialize value types on the evaluation stack of a method's status block when that block is added to the evaluation stack (in other words, when you call the function).

This is because the CLR defines value types in this fashion, as simple values. Generally the perceived "need" for a nondefault initialization of a struct in a higher level context (C#) is due to seeing a struct as something that it isn't. Usually when the default-init behavior of structs is undesirable, the type in question should not be a struct.

It's a design decision based around having value types be relatively small, efficient objects while retaining a more-unified and streamlined system.

C# could, in theory, abstract this and allow customized default "constructors." But they have chosen not to. *shrug*

Share this post


Link to post
Share on other sites

This topic is 2852 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this