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 // ...
};
}
}
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".
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With