【问题标题】:custom extension methods collide with framework extension methods. Why?自定义扩展方法与框架扩展方法发生冲突。为什么?
【发布时间】:2010-12-30 22:21:55
【问题描述】:

我在我们的应用程序中有一个奇怪的行为。我想遍历表的行 (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 语句来删除对扩展方法的任何引用。但这有一个令人讨厌的副作用,即迫使我们完全限定任何类型声明。不漂亮。

提前感谢您的任何意见。

埃里克。

【问题讨论】:

  • 我相信您可以尝试编写一个简短但完整的示例,just 显示了该问题。毕竟,您所要做的就是创建一个DataTable 并调用AsEnumerable。如果您可以从编译器发布 exact 错误消息,那将有很大帮助。

标签: c# datatable extension-methods


【解决方案1】:

也许以下方法效果最好:

foreach (DataRow dr in table.Rows)
{
}

【讨论】:

    【解决方案2】:

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

    以下代码显示选择了最派生的编译时类型扩展方法。 它适用于您的代码吗?

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

    【讨论】:

      【解决方案3】:

      我不太确定您为什么会遇到这个问题,但一种可能的解决方法是放弃扩展方法语法糖,将 AsEnumerable 视为普通静态方法:

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

      【讨论】:

        【解决方案4】:
        foreach(var thing in ((DataTable)table).AsEnumerable())
        {
        ...
        }
        

        试试看....

        【讨论】:

          【解决方案5】:

          您可以使用 using [alias = ]class_or_namespace; 的别名 = 部分。然后你会得到类似using my = System.Data; 的东西,然后将它与my.DataTable.AsEnumerable(); 一起使用

          【讨论】:

          • Yuriy,你能否发布一个快速的 sn-p 来展示如何将“使用”与扩展方法一起使用。我想维护 table.AsEnumerable() 语法。我相信您建议切换到 AsEnumerable(table) ,这在我们的上下文中并不那么清楚。问候。
          猜你喜欢
          • 2011-07-14
          • 1970-01-01
          • 2010-09-29
          • 2014-10-12
          • 1970-01-01
          • 2016-07-29
          • 2013-08-09
          • 2012-09-10
          相关资源
          最近更新 更多