现在我早就知道并且习惯于在C#中使用这种行为,一般来说,我喜欢它。但有时编译器不够智能。
我有一小段代码,现在我的解决方法不是一个大问题,但可能是类似的情况。
bool gap=false;
DateTime start; // = new DateTime();
for (int i = 0; i < totaldays; i++)
{
if (gap)
{
if (list[i])
{
var whgap = new WorkHistoryGap();
whgap.From = start; //unassigned variable error
whgap.To = dtFrom.AddDays(i);
return whgap;
}
}
else
{
gap = true;
start = dtFrom.AddDays(i);
}
}
我遇到的问题是,如果你必须使用没有默认构造函数的非可空结构来执行此操作?如果start
不是简单的DateTime对象,那么还是可以解决这个问题吗?
答案 0 :(得分:10)
有时编译器不够智能
您希望编译器解决的问题等同于暂停问题。由于计算机程序无法解决该问题,因此我们只做了最小的尝试来解决它。我们没有做任何特别复杂的事情。你将不得不忍受它。
有关为什么程序分析等同于暂停问题的更多信息,请参阅我的文章,该文章主题是推断方法的终点是否可达。这与确定变量是否明确分配的问题基本相同;分析非常相似。
http://blogs.msdn.com/b/ericlippert/archive/2011/02/24/never-say-never-part-two.aspx
如果必须使用没有默认构造函数的非可空结构来执行此操作,该怎么办?
没有这样的动物。所有结构,可以为空或以其他方式具有默认构造函数。
如果start不是一个简单的DateTime对象,还是可以解决这个问题吗?
表达式default(T)
为您提供任何类型T的默认值。您可以随时说
Foo f = default(Foo);
并有法律任务。如果Foo是值类型,则它调用默认构造函数,该构造函数始终存在。如果它是引用类型,那么您将获得null。
答案 1 :(得分:6)
由于您的DateTime
变量,编译器无法确定您是否可以设置gap
。
只需使用
DateTime start = DateTime.Now;
并完成它。
修改更好的是,第二眼看看您的代码,请使用
DateTime start = dtFrom;
答案 2 :(得分:4)
struct
中没有默认构造函数。试试吧:
struct MyStruct {
public MyStruct() {
// doesn't work
}
}
您可以拥有静态构造函数,但无法为struct
定义默认构造函数。这就是为什么在这么多结构上有静态方法Create
的原因,以及为什么你可以说new Point()
而不是Point.Empty
。
任何struct
的“默认构造函数”始终将其所有字段初始化为其默认值。 certian类型的Empty
静态字段是为了方便起见。它实际上在性能上没有差别,因为它们是值类型。
答案 3 :(得分:3)
在我看来,你的bool gap
和DateTime start
实际上是一回事。尝试这样的重构:
DateTime? gapStart = null ;
for (int i = 0; i < totaldays; i++)
{
if ( gapStart.HasValue )
{
if (list[i])
{
var whgap = new WorkHistoryGap();
whgap.From = gapStart.Value ; //unassigned variable error
whgap.To = dtFrom.AddDays(i);
return whgap;
}
}
else
{
gapStart = dtFrom.AddDays(i);
}
}
[编辑注意:请发布代码样本......哦...实际编译。它使它更容易。]
[进一步编辑注意:您将gap设置为true并在循环中第一次设置start
值。进一步重构这样的事情:]
DateTime gapStart = dtFrom.AddDays( 0 );
for ( int i = 1 ; i < totaldays ; i++ )
{
if ( list[i] )
{
var whgap = new WorkHistoryGap();
whgap.From = gapStart.Value; //unassigned variable error
whgap.To = dtFrom.AddDays( i );
return whgap;
}
}
答案 4 :(得分:1)
为什么要尝试解决语言设计问题?即使编译器可以提前计算出你的整个循环,这在编译器方面似乎是不必要的复杂,它如何知道不能在代码的某些部分抛出异常?您必须为start
分配一个值,因为您稍后会在代码中使用它,可能在它(根据您)不可避免的分配之前使用它。