C#中的显式结构需要double init值

mal*_*loo 3 c#

以下C#结构用于表示颜色分量和32位颜色值本身的并集.问题是编译器给出了错误:

错误CS0171在将控制权返回给调用者之前,必须完全分配字段'Color.ARGB'

是否可以在不初始化数据两次的情况下消除此错误?这是C#的预期行为吗?如果我初始化两次,JIT会检测到双初始化并且只执行第二次初始化吗?

[StructLayout(LayoutKind.Explicit)]
public struct Color
{
    public Color(byte r, byte g, byte b, byte a = 0xff)
    {
        ARGB = 0; // The init I shouldn't have to do
        A = a;
        R = r;
        G = g;
        B = b;
    }

    [FieldOffset(0)]
    public byte B;
    [FieldOffset(1)]
    public byte G;
    [FieldOffset(2)]
    public byte R;
    [FieldOffset(3)]
    public byte A;
    [FieldOffset(0)]
    public uint ARGB;

    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 6

是否可以在不初始化数据两次的情况下消除此错误?

是的,不是.

这里的假设是成员尚未"初始化两次".当您从内存分配器获取新结构时 - 无论是从堆还是堆栈 - 它将自动归零.

正如Naidu的回答所说,调用默认构造函数向编译器指示"运行时必须将此事件归零(如果它还没有);我希望断言对于未被构造函数写入的对象的任何部分,我很好它的默认状态".

实际上,通常抖动已经初始化为零,因此通常不会进行额外的初始化.但是,内存分配器自动将状态初始化为零的行为依赖于运行时实现.同样是实现相关的行为,如果抖动是否能优化掉零出的行为知道,每场被初始化.

这里有微妙之处.假设例如内存未被清零,因为抖动推断出构造函数会写入每个字段.现在假设在构造函数的中途抛出线程中止异常.是否有可能另一个线程观察对象的未归零,未写入状态?如果事实上有可能会发生什么样的地狱般的行为呢?给出一些想法.

这是C#的预期行为吗?

是.

编译器不知道你正在创建一个类型不安全的联合.它不知道这些属性的含义.

如果我初始化两次,JIT会检测到双初始化并且只执行第二次初始化吗?

许多不同的平台上有许多不同的紧张情绪.如果您想要回答您的问题,请使用所有可能的配置尝试所有问题并查看会发生什么.

无论如何,你可能会担心没什么重要的.将零写入内存非常快.执行不必要的零写操作可能不是程序中的瓶颈.


Pav*_*aka 6

查看下面的微软链接:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0843

它说,

要从构造函数为自动实现的属性赋值,必须首先调用默认构造函数来创建对象。

进行以下更改将解决您的问题。调用默认构造函数。

 public Color(byte r, byte g, byte b, byte a = 0xff):this()
 {
         A = a;
         R = r;
         G = g;
         B = b;
  }
Run Code Online (Sandbox Code Playgroud)