如何初始化struct?

Yip*_*Yay 53 c# struct initialization

我应该在我的任意结构中实现什么成员才能使以下任务成为可能:

public struct MyStruct {
   String s;
   Int length;
}

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 };

// Now, I want the following code to set the 's' to "Lol" and the
// length to 3 (length of "Lol"). The second part should be done
// automatically.
myStruct = "Lol"; // Or myStruct = String("Lol");
Run Code Online (Sandbox Code Playgroud)

该怎么做?

Guf*_*ffa 90

您使用隐式运算符将字符串值转换为结构值:

public struct MyStruct {
  public string s;
  public int length;

  public static implicit operator MyStruct(string value) {
    return new MyStruct() { s = value, length = value.Length };
  }

}
Run Code Online (Sandbox Code Playgroud)

例:

MyStruct myStruct = "Lol";
Console.WriteLine(myStruct.s);
Console.WriteLine(myStruct.length);
Run Code Online (Sandbox Code Playgroud)

输出:

Lol
3
Run Code Online (Sandbox Code Playgroud)

  • @ZEE:`new`运算符不区分结构的堆分配。实际上,没有任何无参数的构造函数可调用,而只是用于创建结构值的C#语法。 (2认同)

sup*_*cat 10

在任何可行的情况下,结构类型应该将所有状态封装在公共字段中,这些字段可以独立地设置为对其各自类型有效的任何值,或者表现为单个统一值,只能通过构造函数,工厂设置,方法,或者通过将struct的实例作为显式ref参数传递给它的一个公共方法.与某些人声称的相反,具有公共字段的结构没有任何问题,如果它应该表示一组值,这些值可以合理地单独操作或作为一组传递(例如点的坐标).历史上,有公共财产制定者的结构存在问题,并且避免公共领域的意图(暗示应该使用制定者)已经导致一些人建议应该完全避免可变结构,但是字段没有财产有的问题.事实上,露出的场结构是独立变量的松散集合了理想的表现,因为它变量只是一个松散的集合.

但是,在您的特定示例中,似乎结构的两个字段可能不应该是独立的.您可以通过三种方式合理地设计结构:

  • 您可以将唯一的公共字段作为字符串,然后调用只读"helper"属性length,如果字符串为非null,则报告其长度;如果字符串为null,则返回0.

  • 您可以让结构不公开任何公共字段,属性设置器或变异方法,并且在对象的构造函数中指定唯一字段的内容 - 私有字符串.如上所述,length将是一个报告存储字符串长度的属性.

  • 你可以让struct不暴露任何公共字段,属性设置器或变异方法,并有两个私有字段:一个用于字符串,一个用于长度,两者都将在一个带字符串的构造函数中设置,存储它,衡量其长度,并存储.确定字符串的长度足够快,以至于计算和缓存它可能是不值得的,但是有一个结合了字符串及其GetHashCode值的结构可能是有用的.

重要的是要注意关于第三种设计的细节,但是:如果非线程安全代码导致在另一个线程写入结构时读取结构的一个实例,则可能导致意外创建结构实例,字段值不一致.结果行为可能与以非线程安全方式使用类时出现的行为略有不同.任何与安全有关的代码都必须小心,不要假设结构字段将处于一致状态,因为恶意代码 - 即使在"完全信任"环境中 - 可以轻松生成状态不一致的结构,如果这是什么它想做.

PS - 如果您希望允许使用字符串赋值来初始化您的结构,我建议使用隐式转换运算符并使其Length成为只读属性,如果非null,则返回基础字符串的长度,或者如果字符串为null,则返回零.

  • 尽管您提出了一些有趣的观点,但这实际上并没有回答问题。 (3认同)

Sco*_*ski 5

  1. "长度"是否会偏离"s"的实际长度.如果答案是否定的,那么你不需要存储长度,因为字符串已经存储它们的长度,你可以只调用s.Length.

  2. 要获得您要求的语法,您可以实现"隐式"运算符,如下所示:

    static implicit operator MyStruct(string s) {
        return new MyStruct(...);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 无论您是否使结构可变,隐式运算符都将起作用.