5

次のメッセージがあります。

警告:フィールドが割り当てられることはなく、常にデフォルト値が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#コンパイラのバグですか、それとも何かを見逃しましたか?

UPDATEフィールドは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 // ...
        };
    }
}
4

4 に答える 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演算子を使用するだけです(つまり、フィールドハンドルを直接埋め込みます。名前のaは使用しませんstring)。

同じロジックで、デリゲートにすると警告は消えます。

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

これコードです。これは、 「コンパイルされた場合、これが私が行うこと」を示す単なるオブジェクトモデルではありません。

于 2012-09-21T09:11:22.197 に答える
1

はい、それはコンパイラの欠点のようです。どうやらそれは表現を見通すことができない(含まない)。
以下は、期待どおりに「bbc」を出力します。

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

MyClassのプライベートコンストラクターのようないくつかのトリックを試しましたが、警告が残ります。

コンパイラはより保守的なアルゴリズムを適用し、(通常の)メンバーがに割り当てられているかどうかのみをチェックしているようdbMyPropです。


名前に2つの異なる要素があるため、混乱していますがdbMyPropMyEntity.MyPropここに書き込まれることはありません。

于 2012-09-21T09:10:39.377 に答える
0

コンパイラのバグではありません。

pls。MarcGravellによる回答を参照してください

次の説明は正しくありません。


次のシーンでは、割り当てられていない値が使用されるため、警告が表示されますdbMyProp。1.MyClassがインスタンス化されます。2.インスタンスMyPropプロパティの使用が呼び出されます。(これはにつながりますNullReferenceException

于 2012-09-21T09:09:03.053 に答える
0

または私は何かを逃しましたか?

あなたは何かを逃しました。ラムダ式の中で、の新しいインスタンスを作成し、そのフィールドMyClassを割り当てました。ただし、インスタンスメソッド内で現在のインスタンスのフィールドをdbMyProp割り当てたことはありません。dbMyProp

この例を確認してください。

var instance = new MyClass();
var myProp = instance.MyProp; // BOOM - you never assigned a value to the dbMyProp field
于 2012-09-21T09:09:57.647 に答える