C# 在LINQ扩展方法中指定泛型类型的原因

C# 在LINQ扩展方法中指定泛型类型的原因,c#,linq,generics,extension-methods,C#,Linq,Generics,Extension Methods,只是出于好奇: 许多LINQ扩展方法同时作为泛型和非泛型变体存在,例如Any和Any,Where和Where等。编写查询时,我通常使用非泛型变体,效果很好 如果必须使用通用方法,会出现什么情况 ---编辑--- 注意:我知道在内部只调用泛型方法,编译器在编译过程中试图解析泛型括号的内容。 我的问题是,如果必须显式地提供类型,而不是依赖于编译器的直觉,那么情况是什么。C#编译器足够聪明,可以根据参数推断出方法的类型。当类型是匿名的,因此没有名称时,这一点很重要 obj.SomeMethod(123

只是出于好奇:

许多LINQ扩展方法同时作为泛型和非泛型变体存在,例如
Any
Any
Where
Where
等。编写查询时,我通常使用非泛型变体,效果很好

如果必须使用通用方法,会出现什么情况

---编辑---

注意:我知道在内部只调用泛型方法,编译器在编译过程中试图解析泛型括号的内容。 我的问题是,如果必须显式地提供类型,而不是依赖于编译器的直觉,那么情况是什么。C#编译器足够聪明,可以根据参数推断出方法的类型。当类型是匿名的,因此没有名称时,这一点很重要

obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);

obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
obj.SomeMethod(123)//这些电话都是一样的
目标方法(123);
obj.SomeMethod(new{foo=123})//我会在这里写什么类型?!
编辑:要清楚,您总是调用泛型方法。它看起来只是一个非泛型方法,因为编译器和Intellisense是智能的

编辑:对于更新后的问题,如果要使用的类型不是要传递的对象的类型,则需要具体说明。有两种情况:

  • 如果参数实现了一个接口,并且您希望在该接口上操作,而不是具体类型,那么您应该指定接口:

    obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
    
    obj.DoSomething(新列表());
    
  • 如果参数可隐式转换为另一种类型,并且您希望使用第二种类型,则应指定它:

    obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
    
    obj.DoSomethingElse(123)//123实际上是一个int,但可以转换为long
    
  • 另一方面,如果您需要强制转换来进行转换(或插入一个),则无需指定:

    obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
    
    obj.DoYetAnotherThing((转换)new MyThing());//叫DoYetAnotherThing
    
    始终。C#编译器足够聪明,可以根据参数推断出方法的类型。当类型是匿名的,因此没有名称时,这一点很重要

    obj.SomeMethod(123); //these calls are the same
    obj.SomeMethod<int>(123);
    
    obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
    
    obj.SomeMethod(123)//这些电话都是一样的
    目标方法(123);
    obj.SomeMethod(new{foo=123})//我会在这里写什么类型?!
    
    编辑:要清楚,您总是调用泛型方法。它看起来只是一个非泛型方法,因为编译器和Intellisense是智能的

    编辑:对于更新后的问题,如果要使用的类型不是要传递的对象的类型,则需要具体说明。有两种情况:

  • 如果参数实现了一个接口,并且您希望在该接口上操作,而不是具体类型,那么您应该指定接口:

    obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
    
    obj.DoSomething(新列表());
    
  • 如果参数可隐式转换为另一种类型,并且您希望使用第二种类型,则应指定它:

    obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
    
    obj.DoSomethingElse(123)//123实际上是一个int,但可以转换为long
    
  • 另一方面,如果您需要强制转换来进行转换(或插入一个),则无需指定:

    obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
    
    obj.DoYetAnotherThing((转换)new MyThing());//叫DoYetAnotherThing
    
    我今天遇到的一个例子:

    ObjectSet<User> users = context.Users;
    var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));
    
    另两个更常见的示例是类型的
    Cast
    方法,它们无法推断您想要什么类型,并且在许多情况下,首先对非泛型集合进行调用


    总的来说,设计LINQ方法的人不遗余力地避免在这些泛型方法中使用显式类型,而且在大多数情况下,您不需要这样做。我想说,最好知道这是一种选择,但除非你觉得有必要,否则不要这样做。

    我今天遇到的一个例子是:

    ObjectSet<User> users = context.Users;
    var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));
    
    另两个更常见的示例是类型
    Cast
    方法,它们无法推断您想要什么类型,并且在许多情况下,首先对非泛型集合进行调用


    总的来说,设计LINQ方法的人不遗余力地避免在这些泛型方法中使用显式类型,而且在大多数情况下,您不需要这样做。我想说,最好知道这是一种选择,但除非你觉得有必要,否则不要这样做。

    非常感谢。我知道,在内部,泛型方法调用是由编译器解决的。我的问题的目标是当if能够显式指示类型时带来任何好处的情况。例如,如果编译器试图将类型解析为某种类型的接口,并且确实希望使用派生类型的方法和属性等。我编辑了我的问题以使其更清楚。我认为这应该回答您的问题。应该注意的是,编译器永远不会从具体类型推断接口。它只会推断出一个接口,如果你给它的类型也是一个接口。太好了,谢谢你添加了更多的例子,它帮助了我很多!多谢各位。我知道,在内部,泛型方法调用是由编译器解决的。我的问题的目标是当if能够显式指示类型时带来任何好处的情况。例如,如果编译器试图将类型解析为某种类型的接口,并且确实希望使用派生类型的方法和属性等。我编辑了我的问题以使其更清楚。我认为这应该回答您的问题。应该注意的是,编译器永远不会从具体类型推断接口。它只会推断出一个接口,如果你给它的类型也是一个接口。太好了,谢谢你添加了更多的例子,它帮助了我很多!我不知道是谁否决了你,但把原来的问题标题和文本重新写给我可能会有帮助