我应该在我的任意结构中实现什么成员才能使以下任务成为可能:
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");
应如何做?
答案 0 :(得分:88)
使用隐式运算符将字符串值转换为结构值:
public struct MyStruct {
public string s;
public int length;
public static implicit operator MyStruct(string value) {
return new MyStruct() { s = value, length = value.Length };
}
}
示例:
MyStruct myStruct = "Lol";
Console.WriteLine(myStruct.s);
Console.WriteLine(myStruct.length);
输出:
Lol
3
答案 1 :(得分:9)
结构类型应该在任何可行的情况下将所有状态封装在公共字段中,这些字段可以独立地设置为对其各自类型有效的任何值,或者表现为单个统一值,只能通过构造函数,工厂,方法,或者通过将结构的实例作为显式ref
参数传递给它的一个公共方法。与某些人声称的相反,具有公共字段的结构没有任何问题,如果它应该表示一组值,这些值可以合理地单独操作或作为一组传递(例如点的坐标)。历史上,有公共财产制定者的结构存在问题,并且避免公共领域的意图(暗示应该使用制定者)已经导致一些人建议应该完全避免可变结构,但是字段没有财产有的问题。实际上,暴露字段结构是松散的自变量集合的理想表示,因为它只是一个松散的变量集合。
但是,在您的特定示例中,您的结构的两个字段似乎不应该是独立的。您可以通过三种方式合理地设计结构:
您可以将唯一的公共字段作为字符串,然后使用名为length
的只读“帮助程序”属性,如果字符串为非空,则返回零,或返回零如果字符串为空。
您可以让struct不公开任何公共字段,属性设置器或变异方法,并且在对象的构造函数中指定唯一字段的内容 - 私有字符串。如上所述,length
将是一个报告存储字符串长度的属性。
您可以让struct不公开任何公共字段,属性设置器或变异方法,并且有两个私有字段:一个用于字符串,一个用于长度,两者都将在构造函数中设置取一个字符串,存储它,测量它的长度,然后存储它。确定字符串的长度足够快,以至于计算和缓存它可能是不值得的,但是有一个结合字符串及其GetHashCode
值的结构可能很有用。
重要的是要了解有关第三种设计的细节,但是:如果非线程安全代码导致在另一个线程正在写入时读取结构的一个实例,则可能导致意外创建结构实例,其字段值不一致。结果行为可能与以非线程安全方式使用类时出现的行为略有不同。任何与安全有关的代码都必须小心,不要假设结构字段将处于一致状态,因为恶意代码 - 即使在“完全信任”环境中 - 可以轻松生成状态不一致的结构,如果这是什么它想做。
PS - 如果您希望允许使用字符串中的赋值来初始化结构,我建议使用隐式转换运算符并使Length
成为只读如果为非null,则返回基础字符串长度的属性;如果字符串为null,则返回零。
答案 2 :(得分:5)
“长度”是否会偏离“s”的实际长度。如果答案是否定的,那么你不需要存储长度,因为字符串已经存储它们的长度,你可以只调用s.Length。
要获得您要求的语法,您可以实现“隐式”运算符,如下所示:
static implicit operator MyStruct(string s) {
return new MyStruct(...);
}
隐式运算符将起作用,无论您是否使结构变为可变。
答案 3 :(得分:1)
你的结构可以有方法和属性......为什么不尝试
public struct MyStruct {
public string s;
public int length { return s.Length; }
}
更正 @ Guffa的答案显示有可能...更多信息:http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx