C# 无法推断出 var(结构类型)在我使用它的地方被初始化。怎么修?

C# fails to deduce a var (of a struct type) is initialized where I'm using it. How to fix?

C# 编译器认为某些变量未赋值,而实际上它们是。我想这是一个棘手的情况,编译器无法弄清楚。

using System.Drawing;   // for Point struct

Point P1,P2,P3;   // they're undefined here, of course
List<Point> points = new List<Point>();

if (rainbows)   {
    P1 = new Point(100,200);
    points.Add(P1);
}
if (butterflies)   {
    P2 = new Point(444,555);
    points.Add(P2);
}
if (unicorns)    {
    P3 = new Point(123,456);
    points.Add(P3);
}

// Usually will have three points here, but if not, quit    
if (points.Count < 3)  return false;

// We have three points here. 
// For sure, P1, P2, P3 have all been assigned
DoSomethingWithPoint(P1);   // ERROR unassigned var P1

调用 DoSomethingWithPoint() 时,如何告诉 C# 编译器理解一切正常?我知道可以关闭警告,但是错误呢?

有没有办法调整此代码以使其编译并运行?

P1 已定义,但 unassigned/uninitialized 如果彩虹不是真的。你可以给它赋初值'null',让它赋值。

您可以将您的点与集合和方法一起设置为 Nullable。

        Point? P1 =  null;
        Point? P2 = null;
        Point? P3 = null;
        List<Point?> points = new List<Point?>();
        bool rainbows = true;
        bool butterflies = false;
        bool unicorns = true;

        if (rainbows)
        {
            P1 = new Point(100, 200);
            points.Add(P1);
        }
        if (butterflies)
        {
            P2 = new Point(444, 555);
            points.Add(P2);
        }
        if (unicorns)
        {
            P3 = new Point(123, 456);
            points.Add(P3);
        }

        // Usually will have three points here, but if not, quit    
        if (points.Count < 3) { }

        // We have three points here. 
        // For sure, P1, P2, P3 have all been assigned
        DoSomethingWithPoint(P1);   // ERROR unassigned var P1

您可以:

Point P1 = default(Point), P2 = default(Point), P3 = default(Point);

我不确定我会那样做,但是如果你 want/have 给 P1...P3 一些默认值,default(Point) 是结构的默认值。

如果您的条件之一不合格,请尽早 return 退出:

Point P1,P2,P3;

if (!rainbows)   {
    return false;
}
P1 = new Point(100,200);

if (!butterflies)   {
    return false;
}
P2 = new Point(444,555);

}
if (!unicorns)    {
    return false;
}
P3 = new Point(123,456);

// ... You might even be able to get rid of `points` if you don't use it:
List<Point> points = new List<Point> { P1, P2, P3 };

DoSomethingWithPoint(P1);

C# 编译器can't 证明在每种情况下都分配了 P1;它只对每个未分配的变量进行非常简单的可达性分析。任何更复杂的东西实施起来都会非常昂贵。

你是对的;在 // For sure, P1, P2, P3 have all been assigned 点,所有点实际上都已分配。你知道这一点,我也知道这一点,但是编译器无法证明这一点。

在一般情况下,证明一个变量是否被赋值是不可能的。因为它被证明是不可能的(你可以查找 details/proofs 的停机问题),编译器必须使用不完美的算法(启发式算法,从本质上猜测哪些变量 可能 不赋值)。它没有任何误报(如果它说一个变量有一个值,那么该变量将始终有一个值)但是有一些误报。

您需要 "trick" 编译器,以一种或另一种方式,通过明​​确表示变量已明确分配,使用某种方式证明变量实际上有一个价值。将变量初始化为某个值(default(Point) 可能是一个不错的选择),即使您知道它永远不会被使用,也是一种可能的方法。

没有办法只是 "turn the error off" 而忽略它。您需要以某种方式更改代码,以便编译器实际上可以证明您解析为值的任何变量都已分配了一个值。