【问题标题】:LinqToSql - Extension Method ResolutionLinqToSql - 扩展方法解析
【发布时间】:2018-07-06 16:41:32
【问题描述】:

我了解在编译时解析期间,实例方法优先于扩展方法。但是对于 LinqToSQL(或 LinqtoXXX):

Table<Order> orders = context.Orders
var query = orders.Where(o=>o.name=="xyz")

解决上述Queryable 类的Where 方法的决定因素是什么?尽管Table&lt;Order&gt; 实现了IEnumerabe&lt;T&gt;IQueryable&lt;T&gt;

public sealed class Table<TEntity> : IQueryable<TEntity>, IQueryable, 
                                         IEnumerable<TEntity>, IEnumerable,
                                         ITable<TEntity>, ITable,
                                         IQueryProvider, 
                                         IListSource
        where TEntity : class
    {
        // ...
    }

【问题讨论】:

    标签: c# linq extension-methods overload-resolution


    【解决方案1】:

    EntityFramework 使用 IQueryable 为 context.Orders 启用 Linq-To-Sql。

    不同的是,IQueryable 是允许 LINQ-to-SQL(LINQ.-to-anything 真的)工作。所以如果你进一步 在 IQueryable 上优化您的查询,该查询将在 数据库,如果可能的话。

    对于 IEnumerable 情况,它将是 LINQ-to-object,这意味着 与原始查询匹配的所有对象都必须加载到 数据库中的内存。

    欲了解更多信息,请参阅:Returning IEnumerable<T> vs. IQueryable<T>

    编辑 29/01/2018

    如果您的类具有为 2 个接口定义的同名扩展方法 结果如下:

    public interface IA
    {
        void SayHello();
    }
    public interface IB
    {
        void SayHello();
    }
    
    public class AB: IA,IB
    {
        //If two interfaces have methods with same signature, 
        //They can both be implemented by prefixing interface name for one of them.
        void IA.SayHello()
        {
            Console.WriteLine("Hello A");
        }
    
        void IB.SayHello()
        {
            Console.WriteLine("Hello B");
        }
    
        public void SayHello()
        {
            Console.WriteLine("Hello AB");
        }
    }
    
    public static class MyClassExt
    {
        public static void SayBye(this IA a)
        {
            Console.WriteLine("Bye from A");
        }
    
        public static void SayBye(this IB b)
        {
            Console.WriteLine("Bye from B");
        }
    
        public static void SayBye(this AB ab)
        {
            Console.WriteLine("Bye from AB");
        }
    }
    
    var obj = new AB();
    
    obj.SayHello(); //Hello AB
    ((IA)obj).SayHello(); //Hello A
    ((IB)obj).SayHello(); //Hello B
    
    obj.SayBye(); //Bye AB
    ((IA)obj).SayBye(); //Bye A
    ((IB)obj).SayBye(); // Bye B
    

    您还可以通过Test inheritence and extension methods.linq 获取 LinqPad 脚本

    【讨论】:

    • 我理解两个接口的区别。我的好奇心更多的是当类同时实现接口并且为它们定义扩展方法时扩展方法的编译时解析
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多