簡體   English   中英

定制擴展方法與框架擴展方法相沖突。 為什么?

[英]custom extension methods collide with framework extension methods. Why?

我的應用程序中有一個奇怪的行為。 我想遍歷表( DataTable )的行。 我想使用DataTableExtensions類中的AsEnumerable()擴展方法。 像這樣的

foreach(var thing in table.AsEnumerable())
{
...
}

編譯時,它抱怨我需要引用一些ESRI DLL(GIS應用程序)。 經過一番挖掘,我發現了來自引用的DLL的一些擴展方法,這些擴展方法擴展了ESRI中的某些類型(例如IEnumFieldIEnumLayer等)。

顯然, DataTable與其所處的樣子完全不同,我似乎無法找到為什么它試圖綁定到AsEnumerable(this IEnumLayer)而不是AsEnumerable(this DataTable) 有趣的是,我們正在使用Resharper (超棒的工具!),而Resharper站在我們這邊:當您導航到定義時,它將帶您到對象瀏覽器中的AsEnumerable(this DataTable)

在這里,如果不發布數千行專有代碼,就無法在此處發布太多代碼示例,因此,我只是在尋找一次我遇到過相同問題的問題,並使用...類型的答案對其進行了修復

顯而易見的解決方案是通過刪除該名稱空間的所有using語句來刪除對擴展方法的任何引用。 但這具有迫使我們完全限定任何類型聲明的討厭的副作用。 不漂亮。

預先感謝您的任何投入。

埃里克

您可以使用using [alias = ]class_or_namespace;的alias =部分using [alias = ]class_or_namespace; 然后,您將擁有using my = System.Data; 然后將其與my.DataTable.AsEnumerable();

foreach(var thing in ((DataTable)table).AsEnumerable())
{
...
}

嘗試...。

我不太確定為什么會遇到這個問題,但是一個潛在的解決方法是放棄擴展方法語法糖,而只是將AsEnumerable視為普通的靜態方法:

foreach (var thing in DataTableExtensions.AsEnumerable(table))
{
    // do something
}

您可以張貼您的班級層次結構嗎?

下面的代碼顯示選擇了最派生的編譯時類型擴展方法。 它適用於您的代碼嗎?

    [TestMethod]
    public void Test1()
    {
        IEnumerable<MyCustomClass> myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Ignores MyCustomList method and uses IEnumerable<> method.
        Assert.AreEqual(2, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test2()
    {
        MyCustomList myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Uses MyCustomList method
        Assert.AreEqual(1, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test3()
    {
        ISomeInterface myCustomList = new MyCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //If your type is ISomeInterface, the compiler uses ISomeInterface method, even if the runtime instance is MyCustomList
        Assert.AreEqual(0, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test4()
    {
        MyDerivedCustomList myCustomList = new MyDerivedCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //Even if MyDerivedCustomList implements ISomeInterface, the compiler uses MyCustomList method
        Assert.AreEqual(1, myCustomList.Where(x => x.Int1 > 1).Count());
    }

    [TestMethod]
    public void Test5()
    {
        ISomeInterface myCustomList = new MyDerivedCustomList()
                         {
                             new MyCustomClass() { Int1 = 1},
                             new MyCustomClass() { Int1 = 2},
                             new MyCustomClass() { Int1 = 3},
                         };

        //If your type is ISomeInterface, the compiler uses ISomeInterface method, even if the runtime instance is MyDerivedCustomList
        Assert.AreEqual(0, myCustomList.Where(x => x.Int1 > 1).Count());
    }

使用了以下類:

public class MyCustomClass
{
    public int Int1 { get; set; }
}

public class MyCustomList : List<MyCustomClass>, ISomeInterface
{
    public MyCustomList() : base() { }
    public MyCustomList(IEnumerable<MyCustomClass> coll) : base(coll) { }
}

public interface ISomeInterface : IEnumerable<MyCustomClass>
{
}

public class MyDerivedCustomList : MyCustomList, ISomeInterface
{
    public MyDerivedCustomList() : base() { }
    public MyDerivedCustomList(IEnumerable<MyCustomClass> coll) : base(coll) { }
}

public static class MyExtensions
{
    /// <summary>
    /// Where(x => x.Int1 > 2)
    /// </summary>
    public static IEnumerable<MyCustomClass> Where(this MyCustomList myList, Func<MyCustomClass, bool> predicate)
    {
        return new MyCustomList(Enumerable.Where(myList, predicate).Where(x => x.Int1 > 2));
    }

    /// <summary>
    /// Where(x => x.Int1 > 3)
    /// </summary>
    public static IEnumerable<MyCustomClass> Where(this ISomeInterface myList, Func<MyCustomClass, bool> predicate)
    {
        return new MyCustomList(Enumerable.Where(myList, predicate).Where(x => x.Int1 > 3));
    }
}

也許以下方法最有效:

foreach (DataRow dr in table.Rows)
{
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM