2

追加のメソッドが追加されたLINQオブジェクトがあります。このクラスには使い捨てのプロパティやメソッドはありませんが、FxCopは「使い捨てフィールドを所有するタイプは使い捨てである必要があります」というエラーを発生させ、そのクラスを参照しています。

ここまでコードを減らしましたが、それでもエラーが発生します。

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from wiki in context.Wikis
                from pageTag in context.VirtualWikiPageTags
                select new {};

            return null;
        }
    }
}

ただし、from句のいずれかを削除すると、FxCopはエラーを表示しなくなります。

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from pageTag in context.VirtualWikiPageTags
                select new {};

            return null;
        }
    }
}

または

partial class WikiPage
{
    public PagePermissionSet GetUserPermissions(Guid? userId) {
        using (WikiTomeDataContext context = new WikiTomeDataContext()) {
            var permissions =
                from wiki in context.Wikis
                select new {};

            return null;
        }
    }
}

PagePermissionSetは使い捨てではありません。

これは誤検知ですか?それとも、LINQコードはどういうわけかクラスで使い捨てフィールドを生成していますか?誤検知でない場合、FxCopはIDisposableインターフェイスを実装することを推奨していますが、Disposeメソッドで何をしますか?

編集:完全なFxCopエラーは次のとおりです。

「次のIDisposableタイプのメンバーを作成するため、「WikiPage」にIDisposableを実装します。「WikiTomeDataContext」。「WikiPage」が以前に出荷されている場合、このタイプにIDisposableを実装する新しいメンバーを追加すると、既存のコンシューマーに重大な変更が加えられると見なされます。」

編集2:これはエラーを発生させる分解されたコードです:

public PagePermissionSet GetUserPermissions(Guid? userId)
{
    using (WikiTomeDataContext context = new WikiTomeDataContext())
    {
        ParameterExpression CS$0$0001;
        ParameterExpression CS$0$0003;
        var permissions = context.Wikis.SelectMany(Expression.Lambda<Func<Wiki, IEnumerable<VirtualWikiPageTag>>>(Expression.Property(Expression.Constant(context), (MethodInfo) methodof(WikiTomeDataContext.get_VirtualWikiPageTags)), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki") }), Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType8..ctor), new Expression[0], new MethodInfo[0]), new ParameterExpression[] { CS$0$0001 = Expression.Parameter(typeof(Wiki), "wiki"), CS$0$0003 = Expression.Parameter(typeof(VirtualWikiPageTag), "pageTag") }));
        return null;
    }
}

編集3:DataContextへの参照を含むクロージャクラスがあるようです。分解されたコードは次のとおりです。

[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
    // Fields
    public WikiTomeDataContext context;

    // Methods
    public <>c__DisplayClass1();
}
4

4 に答える 4

3

私の推測では、2つのFrom句はSelectMany、データコンテキストを閉じることでへの呼び出しを生成します。クロージャのインスタンスには、FxCop警告の原因となるデータコンテキストへのフィールドがあります。これは心配する必要はありません。

データコンテキストのインスタンスは1つだけで、usingブロックを介してクリーンアップします。クロージャーにはファイナライザーがないため、FxCopの警告にはパフォーマンスや安全性の影響はありません。

于 2009-08-02T16:07:40.703 に答える
2

これは部分的なクラスであることに気づきました。クラスの他の実装ファイルをチェックして、破棄されていないIDisposableメンバーが含まれているかどうかを確認しましたか?

生成されたクロージャに問題があるとは思いません。クロージャは、FxCopがこのような警告を無視する原因となる特定の属性で生成されます。

編集

OPによるさらなる調査により、これはIDisposableフィールドが閉鎖に引き上げられる問題であることが示されました。

残念ながら、これについてできることはたくさんありません。クロージャにIDisposableを実装させる方法はありません。クロージャインスタンスでIDisposableを呼び出す方法がない場合のイベント。

この問題に取り組む最善の方法は、使い捨ての値がクロージャーに取り込まれないようにコードを書き直すことです。使い捨てフィールドは、終了時に常に廃棄する必要があり、クロージャーにキャプチャすると、これを行うことができなくなります。

于 2009-08-02T16:43:42.240 に答える
1

メソッドからLINQクエリを返す場合、コンシューマーはforeachを使用して結果を反復処理します。

コンシューマーがforeachループを終了すると、IEnumerableソース(この場合はLINQクエリ)でdisposeを内部的に呼び出します。これにより、WikiTomeDataContextが破棄されます。

ただし、コンシューマーがLINQクエリを返すメソッドを呼び出したが、結果を繰り返さなかった場合、列挙型は破棄されないように見えます(つまり、ガベージコレクターがオブジェクトをクリーンアップするまで)。これにより、ガベージコレクションまでWikiTomeDataContextが破棄されなくなります。

この問題を回避できる1つの方法は、LINQクエリの結果で.ToArrayを呼び出し、コンテキストでdisposeを呼び出してから、配列を返すことです。

于 2009-08-02T17:36:44.217 に答える
0

エラーを発生させるコードはWikiDataContextを使用します。

エラーが発生しない2つの例では、WikiTomeDataContextを使用します。

たぶん、エラーを引き起こしているこれら2つの間にいくつかの違いがあります。

于 2009-08-02T15:43:24.880 に答える