【问题标题】:Is there any way to trick the compiler into allowing this?有没有办法欺骗编译器允许这样做?
【发布时间】:2018-04-12 15:54:29
【问题描述】:

我有一个相当于

的 XAML 工作流
Bar bar;

if (foo.SomeFlag)
{
    // ... do stuff

    bar = .. // set bar, guaranteed unless exception thrown earlier in this block
}

// do other stuff 

// here it is guaranteed that foo.SomeFlag is the same as it was before
if (foo.SomeFlag)
{
   // use bar
}

在纯 C# 中,我是如何尝试重写它的。问题是我收到Use of unassigned variable 'bar' .. 编译器错误。我理解这个错误,但我想我可以通过写作来克服它

Bar bar;

const bool someFlag = foo.SomeFlag;

if (someFlag)
{
    // ... do stuff

    bar = .. // set bar, guaranteed unless exception thrown earlier in this block
}

// do other stuff 

if (someFlag)
{
   // use bar
}

但显然这不是有效的语法。

任何想法如何克服?

【问题讨论】:

  • 为什么不将bar 设置为null 并稍后检查呢?随着时间的推移,您的标志可能会变得不同步。
  • 您可以使用else 块,但不清楚您要做什么
  • is 实际上是一个已知的明确分配错误,可以 用来欺骗这个,但是您的代码会立即出现错误。不要试图欺骗编译器:只要……给它一个值!
  • 重构你的// Do Other Stuff,不要拆分条件:if (!someFlag) DoOtherStuff(); else { DoStuff(); bar = SetBar() ;DoOtherStuff(); UseBar(bar); }

标签: c# .net visual-studio xaml


【解决方案1】:

编译器要求在使用之前将bar 设置为某个值,并且由于someFlag 可能会在您的if 块之间发生变化(这意味着第一个块可能不会运行,但第二个块可以) ,它会给你一个错误。为避免这种情况,您最初可以将 bar 设置为默认值:

Bar bar = default(Bar);   // this will be 'null' for class objects

那么您的其余代码应该可以按预期工作

const bool someFlag = foo.SomeFlag;

if (someFlag)
{
    // Do something, assign bar to new value
    bar = new Bar();
}

// Do some other stuff 

// Possibly add a check that bar was set, just to be safe...
if (someFlag && bar != null)
{
    // Use bar
    bar.DoSomething();
}

【讨论】:

    【解决方案2】:

    编译器不够聪明,无法识别您的if 块是否会实际执行。因此它假定bar 在使用之前可能无法初始化。为了缓解这种情况,只需通过将 bar 设置为 null 或提供 else 语句来给 bar 一个初始值。

    Bar bar = null;
    
    const bool someFlag = foo.SomeFlag;
    
    if (someFlag)
    {
        // ... do stuff
    
        bar = .. // set bar, guaranteed unless exception thrown earlier in this block
    }
    
    // do other stuff 
    
    if (someFlag)
    {
       // use bar
    }
    

    或者:

    Bar bar;
    
    const bool someFlag = foo.SomeFlag;
    
    if (someFlag)
    {
        // ... do stuff
    
        bar = .. // set bar, guaranteed unless exception thrown earlier in this block
    }
    else
    {
        bar = null;
    }
    
    // do other stuff 
    
    if (someFlag)
    {
       // use bar
    }
    

    【讨论】:

      【解决方案3】:

      欺骗编译器以允许它意味着您的解决方案将有机会出现异常。

      想一想,如果 foo.SomeFlag 不正确会发生什么? bar 的值将为 null,或者更具体地说,它将是 default(Bar)。 (是的,编译器知道任何类型的默认值是什么)。如果像我认为的那样,Bar 是一个类,那么该值肯定为 null。然后当它尝试使用 bar 时,假设您尝试使用 bar.Something 它会抛出异常。编译器实际上是在保护您免受它的侵害。

      解决方案只是在使用 bar 之前进行一次空检查。喜欢:

      if (someFlag)
      {
         if(bar != null)
         {
             // use bar
         }
      }
      

      尽管如此,我强烈建议您开始初始化变量,这样您就可以确定并且不会忘记。喜欢:

      解决方案 1:从 bar 开始。

      Bar bar = null; // <- Only if you know for sure Bar is a class
      // or
      Bar bar = default(Bar);
      
      if (foo.SomeFlag)
      {
          ...
      }
      

      解决方案 2:创建一个 else

      if (foo.SomeFlag)
      {
         ...
      }
      else
      {
          bar = null; // <- Only if you know for sure Bar is a class
          // or
          bar = default(bar);
      }
      ...
      

      【讨论】:

        猜你喜欢
        • 2010-09-18
        • 1970-01-01
        • 2016-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-14
        • 1970-01-01
        相关资源
        最近更新 更多