我今天在创建一个 struct 来保存一堆数据时遇到了这个问题。这是一个例子:
public struct ExampleStruct
{
public int Value { get; private set; }
public ExampleStruct(int value = 1)
: this()
{
Value = value;
}
}
看起来不错,花花公子。问题是当我尝试使用此构造函数而不指定值并希望为参数使用默认值 1 时:
private static void Main(string[] args)
{
ExampleStruct example1 = new ExampleStruct();
Console.WriteLine(example1.Value);
}
这段代码输出0,不输出1。原因是所有结构都有公共(public)无参数构造函数。所以,就像我如何调用 this() 我的显式构造函数一样,在 Main 中,同样的事情发生在 new ExampleStruct() 实际上是调用 ExampleStruct() 但不调用 ExampleStruct(int value = 1)。因为它这样做了,所以它使用 int 的默认值 0 作为 Value。
更糟糕的是,我的实际代码正在检查 int value = 1 参数是否在构造函数的有效范围内。将其添加到上面的 ExampleStruct(int value = 1) 构造函数中:
if(value < 1 || value > 3)
{
throw new ArgumentException("Value is out of range");
}
因此,就目前而言,默认构造函数实际上创建了一个在我需要它的上下文中无效的对象。任何人都知道我可以:
ExampleStruct(int value = 1) 构造函数。ExampleStruct() 构造函数填充默认值的方式。此外,我知道我可以使用这样的字段来代替我的 Value 属性:
public readonly int Value;
但我的理念是私下使用字段,除非它们是 const 或 static。
最后,我使用 struct 而不是 class 的原因是因为这只是一个保存非可变数据的对象,应该在以下情况下完全填充它是构造的,当作为参数传递时,不应该是 null(因为它作为 struct 按值传递),这就是 struct 的设计为。
最佳答案
实际上,MSDN 对struct 有一些很好的指导。
Consider defining a structure instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
Do not define a structure unless the type has all of the following characteristics:
It logically represents a single value, similar to primitive types (integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
It will not have to be boxed frequently.
请注意,它们是考虑 struct 的注意事项,而且它绝不是“这应该总是一个结构”。那是因为选择使用了struct可能会对性能和使用产生影响(正面和负面),应谨慎选择。
特别注意他们不推荐struct对于 > 16 字节的事物(然后复制的成本变得比复制引用更昂贵)。
现在,对于你的情况,除了创建一个工厂来生成 struct 之外,真的没有什么好的方法可以做到这一点。为您处于默认状态或做某种 trick在您的属性(property)中欺骗它在第一次使用时进行初始化。
记住,一个 struct应该这样工作 new X() == default(X) , 即新建一个 struct将包含该 struct 的所有字段的默认值.这很明显,因为 C# 不会让您为 struct 定义无参数构造函数,虽然奇怪的是他们允许所有参数在没有警告的情况下被默认。
因此,我实际上建议您坚持使用 class并使其不可变,只检查 null关于它传递给的方法。
public class ExampleClass
{
// have property expose the "default" if not yet set
public int Value { get; private set; }
// remove default, doesn't work
public ExampleStruct(int value)
{
Value = value;
}
}
但是,如果您绝对必须有一个struct出于其他原因 - 但请考虑 struct 的成本例如复制转换等 - 你可以这样做:
public struct ExampleStruct
{
private int? _value;
// have property expose the "default" if not yet set
public int Value
{
get { return _value ?? 1; }
}
// remove default, doesn't work
public ExampleStruct(int value)
: this()
{
_value = value;
}
}
请注意,默认情况下,Nullable<int>将是 null (即 HasValue == false ),因此如果这是真的,我们还没有设置它,并且可以使用空合并运算符返回我们的默认值 1反而。如果我们确实在构造函数中设置它,它将是非空的并取而代之的值...
关于C# - 调用具有所有默认参数的结构构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13386719/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了