如何防止调用struct的默认构造函数?

时间:2016-04-13 16:44:12

标签: c# struct default-constructor

有没有办法阻止调用结构的默认构造函数?

我的项目中有几个结构,其中一些我无法在任何情况下调用默认构造函数(这将导致我的代码中出现很多不需要的行为)。

PS:任何解决方案只是在编码时指示我某些特殊结构(无法用默认构造函数实例化)正在“错误地”实例化对我来说很好。对我来说,一个简单的编译器警告就足够了!

2 个答案:

答案 0 :(得分:3)

当你处理结构时,C#想要确保你已经初始化了所有结构的字段。

一个选项是提供一个构造函数,它将首先调用默认构造函数,然后再进行自定义初始化:

CURLOPT_SSLCERT => $auth['cert'],
CURLOPT_SSLKEY => $auth['key'],
CURLOPT_USERPWD => $auth['user'],

另一种选择是提供一个构造函数,它可以证明在它自己的体中初始化struct的所有字段,在这种情况下你不需要链接默认的构造函数:

 public S(int x) : this()
 {
     /* custom initialization logic */
 }

另一种选择是跳过调用构造函数,而是在实际使用它之前手动初始化结构:

 public S(int x)
 {
     this.X = x;
     /* custom initialization logic */
 }

在上述选项中,只有第一个执行对默认构造函数的逻辑调用,而其他两个跳过调用。

坏消息是,在幕后,出于安全原因,CLR总是会给你零初始化内存,这几乎完全等同于调用C#默认构造函数。你可以这样观察它:

S s;
s.X = 5;

好消息是,在大多数情况下,这并不重要。 C#默认构造函数不是CLR意义上的构造函数。任何S s; S* ptr = &s; int x = (*ptr).X; Console.WriteLine(x); // will print 0 的表达式new T()等同于T : struct,这只是表达获取类型为default(T)的结构的零初始化实例的一种方式。这也是为什么你不能将它设为私有或为其添加自定义逻辑的原因。

因此,C#默认的struct构造函数不能具有任何逻辑外部可观察的副作用。这给我们带来了一个问题:你试图避免哪种影响?

请记住,如果您的问题是您的结构对于全零位模式无效并且您担心某些客户端代码可能会尝试使用它,则会出现一种解决方法:

T

任何零初始化的结构都将设置其有效性标志,并且只要在结构上执行任何操作(您可以控制),就可以使用它来抛出异常。

毕竟,如果出于任何原因,你仍然需要一个结构实例,它以某种方式跳过调用任何构造函数(无论是真实的还是明显的),你必须自己为结构分配一些内存:

struct S
{
    private bool _isValid;
    /* rest of your struct */
}

您现在可以使用S* ptr = (S*) Marshal.AllocHGlobal(Marshal.SizeOf<S>()); (*ptr).X形式的表达式直接读取和写入该结构。

答案 1 :(得分:2)

正如Aybe指定的那样,你不能这样做,但是你想要你可以在像IsInitialized这样的结构中添加一个默认为false的字段,并使用它来验证值,如果为false则抛出。