How to force use factory for structure in C #

I have a C # structure where I need to prevent the constructor from calling no args on it.

MyStruct a; /// init a by members // OK MyStruct b = MyStruct.Fact(args); // OK, inits by memebers MyStruct s = new MyStruct(); // can't have that 

I do this mainly to force alignment of values ​​for all members, since there are no valid default values, and all members must have valid values.

In C ++, this would be easy, add a private constructor, but C # does not allow this.

Is there any way to prevent this?

I really need to force the factory, so preventing all constructor calls will work as well.


Full description: to avoid mono-dependency, the C # application automatically translates to D, where new Struct() leads to a pointer, and this makes me think. However, this question matters despite this, so just ignore it.

+3
c # struct factory
source share
5 answers

You can not. All structures have an open constructor without parameters by definition in C #. (Almost none of them work in the CLR, but they can always act as if they were.) See this question why you cannot define your own constructors without structs parameters (in C #, anyway).

In fact, you can prevent this statement if you are happy to write your value type in IL. I just checked, and if you make sure that your value type has a constructor without parameters and makes it internal, you cannot write MyStruct ms = new MyStruct(); But this does not interfere:

 MyStruct[] array = new MyStruct[1]; MyStruct ms = array[0]; 

which works around a new limitation - so it really doesn't buy anything. This is really good, as the mess in Il would be dirty.

Are you sure you want to write the structure first? It was almost never a good idea.

+11
source share

You can not.

All values ​​in the structure must be initialized at build time, and there is no way to do this outside the constructor.

What exactly are you trying to do by doing this? Structures are value types, so for most operations you will get a β€œnew” structure. It will be very difficult to fulfill the kinds of constraints that you would use factory for structure.

+3
source share

Anyone can create a structure at any time without calling the constructor if they have access to the structure. Think of it this way:

If you create an array of objects with 1000 elements, all of them are initialized to zeros, so the constructors are not called.

There is no such thing as null in structures. If you create an array with 1000 DateTime objects, they all initialize to zero, which is equal to DateTime.Min. The runtime designers decided to make it possible for you to create an array of structures without calling the constructor N times - a performance that many people did not understand was there.

Your factory idea is good. Will it fit your needs to create an interface and expose it, but make the structure private or internal? It is about as close as you.

+2
source share

Put it in your assembly and use MyStruct () with no arguments as internal (Friend in VB). Have Factory in the same assembly as MyStruct (), but with public access.

Factory can now access the file without MyStruct arguments, but Factory should be used to invoke the assembly from outside.

Edit: bad, I could not take into account that this is a structure. You cannot do this with a structure, only with a class - in this case my previous statement is worth it.

0
source share

You can create a structure that determines whether it is in its initial state by default, and then do something appropriate in this case. I left Factory, but the constructor may also be adequate Factory in a general, simple case.

A lot of templates. Since you are using D, you can think of the same thing as me, "I want C # to have mixins templates."

Example:

 using System; namespace CrazyStruct { public struct MyStruct { private readonly int _height; private readonly bool _init; // Will be 'false' using default(MyStruct). /// <summary> /// Height in centimeters. /// </summary> public int Height { get { if (!_init) { // Alternatively, could have the preferred default value set here. // _height = 200; // cm // _heightInit = true; throw new InvalidOperationException("Height has not been initialized."); } return _height; } // No set: immutable-ish. } private MyStruct(int height) { _height = height; _init = true; } public static MyStruct Factory(int height) { return new MyStruct(height); } } static class Program { static void Main(string[] args) { MyStruct my = MyStruct.Factory(195); Console.WriteLine("My height is {0} cm.", my.Height); try { var array = new MyStruct[1]; var ms = array[0]; Console.WriteLine("My height is not {0} cm.", ms.Height); } catch (Exception ex) { Console.WriteLine("Caught the expected exception: {0}.", ex); } Console.ReadKey(); } } } 
0
source share

All Articles