Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning: Field is never assigned to, and will always have its default value null

I have got following message:

Warning: Field is never assigned to, and will always have its default value null.

My code looks like (it is simplified, so useless):

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 // ...
    };
}

I think that the message is not true.

Is it a bug in C# compiler or I have missed something?

UPDATE The field is dbMyProp. It is simplified but it still produces this warning.

UPDATE2 The following code does not produce such warning:

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 // ...
        };
    }
}
like image 233
TN. Avatar asked Sep 21 '12 09:09

TN.


2 Answers

An Expression is not code. It is intent; so at the compiler level, it could indeed be argued that no code actually ever assigns that field. There is a MemberAssignment (from Expression.Bind), but that is unrelated.

That would only by an actual field assignment if the expression were compiled. And that would be reflection at runtime, which the compiler does not attempt to detect.

Here is what that actually is at compile-time:

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
      }
    );
}

Note what isn't there is any assignment to a field; just use of the imaginary fieldof operator (meaning: it embeds the field handle directly - it doesn't use a string of the name).

And by the same logic, the warning goes away if we make it a delegate:

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

Now this is code; it is not just an object-model showing "here's what I would do, if I were compiled".

like image 133
Marc Gravell Avatar answered Nov 14 '22 21:11

Marc Gravell


Yes, it seems a shortcoming of the compiler. It apparently cannot see through (does not include) the Expression.
The following prints "bbc" as expected:

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

I tried a few tricks like a private constructor on MyClass but the warning remains.

It seems the compiler applies a more conservative algorithm, only checking if any (normal) member assigns to dbMyProp .


You are confusing things by having 2 different elements with the name dbMyProp but MyEntity.MyProp is never written to here.

like image 20
Henk Holterman Avatar answered Nov 14 '22 23:11

Henk Holterman