警告:字段永远不会被分配,并且始终具有默认值 null

问题描述 投票:0回答:4

我收到以下消息:

警告:字段永远不会被分配,并且始终具有默认值 null。

我的代码看起来像(它被简化了,所以没用):

public class MyEntity
{
    // ...
    public string MyProp { get; set; }
}

public class MyClass
{
    string dbMyProp;

    public string MyProp { get { return dbMyProp.Replace("a", "b"); } }

    public static readonly Expression<Func<MyEntity, MyClass>> FromMyEntity = e => new MyClass
    {
        dbMyProp = e.MyProp // ...
    };
}

我认为该消息不属实。

这是 C# 编译器中的错误还是我遗漏了什么?

更新 该字段为

dbMyProp
。它已被简化,但仍然会产生此警告。

UPDATE2 以下代码不会产生此类警告:

public class MyClass2
{
    string dbMyProp;

    public string MyProp { get { return dbMyProp.Replace("a", "b"); } }

    public static MyClass2 FromMyEntity(MyEntity e)
    {
        return new MyClass2 
        {
            dbMyProp = e.MyProp // ...
        };
    }
}
c# compiler-warnings
4个回答
6
投票

Expression
不是代码。这是意图;因此,在编译器级别,确实可以说没有代码实际上分配过该字段。有一个
MemberAssignment
(来自
Expression.Bind
),但这是不相关的。

如果编译了表达式,则只能通过实际的字段赋值来实现。这将是运行时的反射,编译器不会尝试检测到。

这是编译时的实际

static MyClass()
{
    ParameterExpression CS$0$0000;
    FromMyEntity = Expression.Lambda<Func<MyEntity, MyClass>>(
      Expression.MemberInit(
        Expression.New(
          (ConstructorInfo)methodof(MyClass..ctor),
          new Expression[0]
        ),
        new MemberBinding[] {
          Expression.Bind(
            fieldof(MyClass.dbMyProp),
            Expression.Property(
              CS$0$0000 = Expression.Parameter(typeof(MyEntity), "e"),
              (MethodInfo)methodof(MyEntity.get_MyProp)
            )
          )
        }
      ),
      new ParameterExpression[] {
        CS$0$0000
      }
    );
}

注意不是什么有任何对字段的分配;只需使用虚构的

fieldof
运算符(意思是:它直接嵌入字段句柄 - 它不使用名称的
string
)。

按照同样的逻辑,如果我们将其设为委托,警告就会消失

public static readonly Func<MyEntity, MyClass> FromMyEntity = e => new MyClass
{
    dbMyProp = e.MyProp // ...
};

现在这个代码;它不仅仅是一个对象模型,显示“这就是我做的事情,如果我被编译了”。


1
投票

是的,这似乎是编译器的一个缺点。它显然无法看穿(不包括)表达式。
以下按预期打印“bbc”:

var exp = MyClass.FromMyEntity.Compile();
var mc = exp(new MyEntity { MyProp = "abc"});
Console.WriteLine(mc.MyProp);

我尝试了一些技巧,例如 MyClass 上的私有构造函数,但警告仍然存在。

编译器似乎应用了更保守的算法,仅检查是否有任何(正常)成员分配给

dbMyProp


您会因为有两个不同的元素名称为

dbMyProp
而混淆了事情,但
MyEntity.MyProp
从未写到这里。


0
投票

或者我错过了什么?

你错过了一些事情。在 lambda 表达式中,您创建了 MyClass

new
实例,并为其分配了
dbMyProp
字段。但您从未在实例方法内分配
current
实例的 dbMyProp 字段。

查看这个示例:

var instance = new MyClass();
var myProp = instance.MyProp; // BOOM - you never assigned a value to the dbMyProp field

0
投票

这不是编译器中的错误。

请。请参阅 Marc Gravell

的回答

以下解释不正确。


显示警告是因为在以下场景中将使用未分配的

dbMyProp
值。 1.MyClass被实例化。 2. 使用实例
MyProp
属性进行调用。 (这将导致
NullReferenceException

© www.soinside.com 2019 - 2024. All rights reserved.