35
votes

Is it possible to hide the parameterless constructor from a user in C#?

I want to force them to always use the constructor with parameters

e.g. this Position struct

public struct Position
{
    private readonly int _xposn;
    private readonly int _yposn;
    
    public int Xposn
    {
        get { return _xposn; }
    }

    public int Yposn
    {
        get { return _yposn; }
    }

    public Position(int xposn, int yposn)
    {
        _xposn = xposn;
        _yposn = yposn;
    }        
}

I only want users to be able to new up a Position by specifying the x and y coordinates.

However, the parameterless constructor is ALWAYS available.

I cannot make it private. Or even define it as public.

I have read this: Why can't I define a default constructor for a struct in .NET?

but it doesn't really help.

If this is not possible - what is the best way to detect if the Position I am being passed has values?

Explicitly checking each property field? Is there a slicker way?

4

4 Answers

36
votes

No, you can't do this. As you said, similar question has been asked before - and I thought the answer was fairly clear that you couldn't do it.

You can create a private parameterless constructor for a struct, but not in C#. However, even if you do that it doesn't really help - because you can easily work around it:

MyStruct[] tmp = new MyStruct[1];
MyStruct gotcha = tmp[0];

That will be the default value of MyStruct - the "all zeroes" value - without ever calling a constructor.

You could easily add a Validate method to your struct and call that each time you received one as a parameter, admittedly.

5
votes

Nope can't hide it. Structs cannot redefine zero arg constructor, so therefore its visibility can't be redefined.

3
votes

You cannot make a struct with a private parameter-less constructor or even declare a parameter-less constructor. You would have to change it to a class. Structs are not allow to declare a parameterless constructor.

From the Structs Tutorial on MSDN:

Structs can declare constructors, but they must take parameters. It is an error to declare a default (parameterless) constructor for a struct. Struct members cannot have initializers. A default constructor is always provided to initialize the struct members to their default values.

From the C# specification on MSDN:

11.3 Class and struct differences

Structs differ from classes in several important ways:

  • Structs are value types (Section 11.3.1).
  • All struct types implicitly inherit from the class System.ValueType (Section 11.3.2). Assignment to a variable of a struct type creates a copy of the value being assigned (Section 11.3.3).
  • The default value of a struct is the value produced by setting all value type fields to their default value and all reference type fields to null (Section 11.3.4). Boxing and unboxing operations are used to convert between a struct type and object (Section 11.3.5).
  • The meaning of this is different for structs (Section 11.3.6).
  • Instance field declarations for a struct are not permitted to include variable initializers (Section 11.3.7).
  • A struct is not permitted to declare a parameterless instance constructor (Section 11.3.8).
  • A struct is not permitted to declare a destructor (Section 11.3.9).
2
votes

Well a struct is literally a declaration of how the memory will sit.

Even when you use an object, the objects pointer IS declared, regardless of whether it's null.

The reason that you can't hide the constructor is because the struct demands that the CLR can create it as internally it must do this.

You could convert this struct into an object to achieve this task. Or use static analysis to ensure it's intialized before you use it?

struct point
{
   int xpos;
   int ypos;
}

Have a google for immutable objects, this appears to be what your after. I believe that they are looking to add this feature (but not in C# 4) to the language itself, because it is a common requirement. Is there a specific need for a struct here?