tags:

views:

829

answers:

4

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 class

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 availiable

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

I have read this http://stackoverflow.com/questions/333829/why-cant-i-define-a-default-constructor-for-a-struct-in-net

but it doesnt really help

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

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

thanks

A: 

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?

Spence
what do you mean by this?use static analysis to ensure it's intialized you mean check each field has a value?
Christo Fur
You can run a static analysis tool with a rule to ensure that any time someone uses the type in their code that the two values are intialized. or you could do some fancy footwork by declaring it as an object to do the check, and then change to a struct in the release build.
Spence
+3  A: 

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

DavidN
Well, .NET allows you to provide a custom parameterless constructor - but you can't do it *directly* in C# and it doesn't help much anyway, as you can easily work around it.
Jon Skeet
+1  A: 

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).
Ryan
+3  A: 

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 round 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.

Jon Skeet