gpt4 book ai didi

c# - 调用哪个扩展方法

转载 作者:行者123 更新时间:2023-12-04 01:10:43 25 4
gpt4 key购买 nike

我看到了一个像 DBSet 这样的类型,它可以同时实现 IQueryable 和 IEnumerable,如下所示:

public class DbSet<TEntity> : DbQuery<TEntity>, IDbSet<TEntity>, IQueryable<TEntity>, IEnumerable<TEntity>, IEnumerable, IQueryable, ...
很明显IQueryable继承了IEnumerable,并且在System.Linq命名空间中,Enumerable静态类和IQueryable静态类都为IQueryable和IEnumerable定义了一些扩展方法操作符,比如First()、Select(),
我想知道在一些调用中
DBSet<Student> studs = dbContext.Students;
var stu = studs.First();
很明显 public static TSource First<TSource>(this IQueryable<TSource> source);调用 IQueryable 静态类中的方法。
从 C# 规范(7.6.5.2),它说:

If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.


但在我的例子中,System.Linq 命名空间中的 Enumerable 和 IQueryable 类,我想知道在这种情况下 public static T First<T>(this IQueryable<T> source) 是怎么回事?正在决定和调用?

最佳答案

万物皆平等。您的问题归结为标准的重载解析规则。
备注 :阅读语言规范时很重要,不要过早结束或阅读太远。在推广时阅读任何相关的子主题也很重要。
既然你在规范中,让我们通过它们来工作。
给定

public abstract class DbSet<TEntity> : IQueryable<TEntity>, IAsyncEnumerable<TEntity>, IInfrastructure<IServiceProvider>, IListSource

public interface IQueryable : IEnumerable
扩展方法
namespace System.Linq
{
public static TSource First<TSource>(this IQueryable<TSource> source)
...
}

namespace System.Linq
{
public static TSource First<TSource>(this IEnumerable<TSource> source)
...
}
你的例子
DBSet<Student> studs = dbContext.Students;
var stu = studs.First();
您应该引用的规范部分是
强调我的

7.6.5.2 Extension method invocations

...

  • Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
    • If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
    • If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
  • If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
  • Otherwise, overload resolution is applied to the candidate set as described in (§7.5.3).

这考虑到一般标准的重载解析领域。
强调我的

7.5.3 Overload resolution


Overload resolution is a binding-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members. Overload resolution selects the function member to invoke in the following distinct contexts within C#:

...

  • Given the set of applicable candidate function members, the bestfunction member in that set is located. If the set contains only onefunction member, then that function member is the best functionmember. Otherwise, the best function member is the one function memberthat is better than all other function members with respect to thegiven argument list, provided that each function member is compared toall other function members using the rules in §7.5.3.2. If there isnot exactly one function member that is better than all other functionmembers, then the function member invocation is ambiguous and abinding-time error occurs.

这导致我们
强调我的

7.5.3.2 Better function member

For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list.

...

• Otherwise, if MP has more specific parameter types than MQ, then MPis better than MQ



缺点是
  • DbSet实际执行 IQueryable不是 IEnumerable
  • 扩展方法位于相同的命名空间
  • 在这种情况下应用了标准重载解析原则
  • 它构建了一个适用函数成员的候选列表。
  • 应用了更好的函数成员原则。

  • 这使得 IQueryable方法(与确切类型)更好的匹配

    你可以自己测试一下
    给定
    public static class LobExtensions
    {
    public static void Test1(this ILob asd) { }
    }

    public static class BobExtensions
    {
    public static void Test1(this IBob asd) { }
    }

    public interface ILob { }

    public interface IBob : ILob { }

    public class Bob : IBob { }
    用法
    var asd = new Bob();
    asd.Test1();
    结果是 BobExtensions.Test1将是最佳匹配和选择的方法

    关于c# - 调用哪个扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64947663/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com