题
我有一个C#结构在我要禁止呼叫在其上的无参数的构造。
MyStruct a;
/// init a by members // OK
MyStruct b = MyStruct.Fact(args); // OK, inits by memebers
MyStruct s = new MyStruct(); // can't have that
我这样做主要是为了迫使explicet值所有成员没有有效的默认值,所有成员都必须具有有效的值。
在C ++,这将是容易的,添加一个私有构造函数,但C#不允许。
有一种方法,以防止上面的?
我真的需要使用工厂因此防止所有公共构造函数调用将工作一样很好执行。
完整披露:为了避免单依赖性,C#的应用程序正被自动转换为d,其中new Struct()
导致指针并且这碴东西我。但是这个问题是相关的,尽管有这么忽略它。
解决方案
您不能。所有的结构都定义在C#中的公共参数构造函数。 (在CLR几乎没有人做的,但他们总是能够充当如果他们。)请参阅这个问题了解为什么你可以“T限定在结构自己的参数构造函数(在C#,反正)。
其实,你的可以的防止这种说法,如果你乐意写IL你的价值类型。我刚刚检查,如果你确保你的价值只有类型有一个参数的构造函数,并使其内部,你将无法写MyStruct ms = new MyStruct();
但是,这并不妨碍:
MyStruct[] array = new MyStruct[1];
MyStruct ms = array[0];
围绕新的限制工作 - 所以它并没有真正买任何东西。这是相当不错真的,如IL乱搞会是麻烦的。
你确定你真的想成为摆在首位写一个结构?这是几乎的从来就不是一个好主意。
其他提示
您不能。
在一个结构中的所有值必须在施工时被初始化,并没有办法做到这一点的构造函数外。
究竟是你想通过这样做来完成?结构是值类型,所以你会得到大多数操作的“新”的结构。这将是非常难以执行的种种局限的你会在一个结构使用的工厂。
任何人都可以随时创建一个结构,而不调用构造函数,只要他们能够获得的结构。考虑一下这样:
如果您创建对象的1000个元素的数组,他们都得到初始化为null,所以没有构造函数被调用。
使用结构,不存在这样的东西作为空。如果您创建了1000个的DateTime对象的数组,它们都被初始化为零,等于DateTime.Min。运行时的设计者选择了把它,所以你可以创建结构的数组,而不调用构造函数N次 - 性能命中很多人会不知道在那里
。您工厂的想法是好的,但。难道满足您的需求来创建一个接口,揭露这一点,但使结构私有或内部?这是对亲如你会得到。
把它在其自己的组件,并具有不ARGS作为内部(在VB朋友)的MYSTRUCT()。具有在同一组件MYSTRUCT(工厂),但具有一个公共的访问。
现在的工厂可以访问无参数MYSTRUCT,但任何从组件必须使用厂外打来的。
编辑:我的坏,我没有考虑到,这是一个结构。你不能用一个结构做到这一点,只有一类 - 在这种情况下,我先前的发言代表
您可以做检测,如果它是在默认初始化状态一个结构,然后做在这种情况下适当的东西。余留在工厂,但构造也可以是在通用的,简单的情况下的适当的工厂。
这是一个很大的样板代码。由于您使用d,你可能会想我同样的事情,“我希望C#有模板的混入。”
示例:
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();
}
}
}