C# 自定义扩展方法与框架扩展方法冲突。为什么?

C# 自定义扩展方法与框架扩展方法冲突。为什么?,c#,datatable,extension-methods,C#,Datatable,Extension Methods,我在我们的应用程序中有一个奇怪的行为。我想迭代一个表DataTable的行。我想使用DataTableExtensions类中的AsEnumerable扩展方法。例如: foreach(var thing in table.AsEnumerable()) { ... } 当它编译时,它抱怨我需要参考一些ESRI DLLs GIS应用程序。经过一些挖掘,我从引用的DLL中找到了一些扩展方法,这些方法扩展了ESRI中的一些类型,例如IEnumField、IEnumLayer等 显然,DataTab

我在我们的应用程序中有一个奇怪的行为。我想迭代一个表DataTable的行。我想使用DataTableExtensions类中的AsEnumerable扩展方法。例如:

foreach(var thing in table.AsEnumerable())
{
...
}
当它编译时,它抱怨我需要参考一些ESRI DLLs GIS应用程序。经过一些挖掘,我从引用的DLL中找到了一些扩展方法,这些方法扩展了ESRI中的一些类型,例如IEnumField、IEnumLayer等

显然,DataTable与它们完全不同,我似乎无法找到它为什么试图绑定到AsEnumableThis IEnumLayer而不是AsEnumableThis DataTable。有趣的是,我们正在使用Resharper可怕的工具!Resharper站在我们这边:当您导航到定义时,它会将您带到对象浏览器中的一个numerableThisDataTable

我不能在这里发布大量的代码样本而不发布数千行的专有代码,所以我只是在寻找一个我曾经有过相同问题的示例,我用。。。答案的类型

显而易见的解决方案是通过删除该名称空间的所有using语句来删除对扩展方法的任何引用。但这有一个令人讨厌的副作用,那就是迫使我们完全限定任何类型声明。不漂亮

提前感谢您的任何意见


Eric。

您可以使用[alias=]类或名称空间;中的alias=部分;。然后,您可以使用my=System.Data;然后将其与my.DataTable.AsEnumerable一起使用

您可以使用[alias=]类\u或\u命名空间;中的alias=部分;。然后,您可以使用my=System.Data;然后将其与my.DataTable.AsEnumerable一起使用

试试看


尝试一下……

我不太清楚您为什么会遇到这个问题,但一个潜在的解决方法是放弃扩展方法语法糖,只将其视为正常的静态方法:

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

我不太清楚您为什么会遇到这个问题,但一个潜在的解决方法是放弃扩展方法语法糖,只将其视为正常的静态方法:

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

你能发布你的类层次结构吗

下面的代码显示派生最多的编译时类型扩展方法是choosen。 它是否适用于您的代码

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

你能发布你的类层次结构吗

下面的代码显示派生最多的编译时类型扩展方法是choosen。 它是否适用于您的代码

    [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)
{
}

也许以下方法最有效:

foreach (DataRow dr in table.Rows)
{
}

我相信你可以试着写一个简短但完整的例子来说明这个问题。你所要做的就是创建一个DataTable并调用一个numerable。如果你能从编译器中发布准确的错误信息,那将非常有帮助。我相信你可以试着写一个简短但完整的例子来说明这个问题。你所要做的就是创建一个DataTable并调用一个numerable。如果你能从编译器中发布准确的错误消息,那会有很大帮助。Yuriy,你能发布一个快速的代码片段,演示如何使用扩展方法吗。我想维护table.AsEnumerable语法。我相信您建议切换到一个在我们的上下文中不那么清楚的可计算表。Yuriy,你可以发布一个简短的片段来展示如何使用扩展方法吗。我想维护table.AsEnumerable语法。我相信您建议切换到一个在我们的上下文中不那么清楚的可计算表。当做