为什么要在Method <type>()中指定<type>?它是如何使用的?</type> </type>

时间:2013-02-01 05:08:48

标签: c# linq generics types extension-methods

考虑下面的应用程序代码,有3个重载的扩展方法做同样的输入和输出:

  • 使用和调用和定义方法的参数有什么好处(或区别)?
  • 为什么要使用它们(如果没有它们的相同方法3将被调用并执行相同的操作)?
  • 或者如何在方法中手动/明确地使用它们(此类信息)?

代码:

namespace LINQ_CreatingYourFirstExtensionMethod   
{
  internal class Program  
  {
    private static void Main(string[] args)  
    {
      string[] aBunchOfWords = {"One", "Two", "Hello", "World", "Four", "Five"};  
      var iEnuResult =  from s in aBunchOfWords   
                        where s.Length == 5  
                        select s;
      iEnuResult.Write();  
      iEnuResult.Write<string>();
      iEnuResult.Write<object>();//same effect as above line
      Console.ReadKey();
    }  
  }  
} 

重载的扩展方法Write():

namespace LINQ_CreatingYourFirstExtensionMethod  
{  
   public static class Utils  
   {
     public static void Write(this IEnumerable<object> source) //****1 
     //public static void Write(this IEnumerable<string> source)//same effects as above line  
     {
       foreach (var item in source)  
       {
         Console.WriteLine(item);
       }
     }

    public static void Write<T>(this IEnumerable<T> source)//****2
    {
      foreach (var item in source)
      {
        Console.WriteLine(item);
      }
    }

    public static void Write(this IEnumerable source)//******3
    {
      foreach (var item in source)
      {
        Console.WriteLine(item);
      }
    }
  }
}

更新
你能给我一些最简单的插图吗?为什么我需要

  1. 使用<Type>
  2. 调用方法
  3. 使用<Type>
  4. 定义方法

    如果没有它可以做同样的事情吗?

    UPDATE2:
    我没有立刻写出来,因为我认为从问题的背景来看这是显而易见的。

    在当前代码中:

    • iEnuResult.Write();来电 进入第一种方法:
      public static void Write(此IEnumerable源)// * * 1
    • iEnuResult.Write(); (或iEnuResult.Write();)调用
      进入第二个方法: public static void Write1(此IEnumerable来源)// * * 2

    如果要发表评论

    public static void Write1<T>(this IEnumerable<T> source)//*****2
    

    然后

    iEnuResult.Write1<object>(); 
    
    无法制作

    (仅iEnuResult.Write();

    如果要对第一和第二种方法发表评论,那么3d方法将被

    调用
    iEnuResult.Write();
    

    因此,可以在调用(调用)中使用和不使用<Type>调用“相同”方法,以及使用和不使用<Type>的方法定义。

    有多种组合(我会说几十种)看似相同的东西,我看不出太多理由。
    所以,我想了解这种差异存在的目的是什么,如果有的话

1 个答案:

答案 0 :(得分:2)

专注于你的两个问题:

  1. 为什么使用<Type>
  2. 调用方法
  3. 为什么使用<Type>
  4. 定义方法

    第二个问题首先。让我重新说一下:我何时定义泛型方法?

    当方法定位多个类型时,您将定义一个通用方法,但一次只能一个类型。有两大优势:

    • 确保(编译时)类型安全:IEnumerable<string>实际上只包含字符串,而不是奇数或其他。
    • 这是一种使用没有装箱和拆箱的类型的方法(即分别将值类型转换为object)。如上所述here

        

      装箱和拆箱本身就会造成严重的性能损失,但它也会增加托管堆的压力,导致更多的垃圾收集,这对性能来说并不是很好。

    如果您只有非类型化方法(3),则枚举无类型IEnumerable时会将每个字符串装箱(IEnumerator.Current返回Object)并再次取消装箱以调用特定类型{ {1}}方法。并且源列表可以包含任何(这在这里无关紧要,但它经常这样做。)

    通用方法(2)跳过装箱和拆箱,并且类型安全。

    第一种方法强制将任何输入参数(显式或隐式)转换为ToString()。再次,将发生装箱和拆箱。但另一个令人讨厌的事情是,并不总是存在可用的隐式转换,这会强制该方法的使用者在调用它之前显式进行转换。通过将IEnumerable<object>更改为select s可以说明这种效果。如果只有方法1可用,你将获得

      

    实例参数:无法从select s.Length转换为'System.Collections.Generic.IEnumerable<int>'

    我认为拇指的一般规则是避免类型'System.Collections.Generic.IEnumerable<object>'(或object等)的方法参数,除非没有其他选项。

    所以简而言之:你的第二种方法是最好的选择,因为它执行任何类型的任务,但避免装箱和拆箱。

    现在您的第一个问题。什么时候需要在方法调用中指定泛型类型参数?我可以想到三个原因(可能还有更多):

    1. 当没有类型IEnumerable<object>的方法参数时,编译器可以通过该参数推断泛型类型。工厂方法通常属于此类别。像T这样的方法必须通过例如T Create<T>()调用。 Create<Customer>()。构造函数是另一个例子:甚至在没有指定类型的情况下也不能调用泛型构造函数。
    2. 如果要强制使用特定方法重载。当存在具有泛型和非泛型方法重载的混合的继承类型时,可能会发生这种情况。 (顺便说一下,这不是好设计的标志)。
    3. 间接地在编译时不知道类型但仅在执行时知道。见Generics in C#, using type of a variable as parameter