泛型方法经典解释
2011-06-15 11:58
190 查看
首先让我们回忆一下,什么是方法,方法由方法名、括号和方法的参数组成。那么泛型方法,也应该有方法名和括号,但在方法名和括号之间加了一个类型参数,括号中也可以带有方法参数,我们把这种形式的方法称为泛型方法。那么泛型方法有什么用呢?由于有类型参数的存在,这就注定泛型方法就是某种特定方法的模板,由于类型参数的存在,这就使泛型方法抽象了一个层次。我们把它称为某一种特定方法的模板,直到真正使用类型进行确定泛型方法时,泛型方法才具备了真正的意义。方法名称+泛型类型+括号(方法参数)形成了一个泛型方法的整体。
泛型方法是使用类型参数声明的方法,如下所示:
请看下面的泛型方法Swap<T>() ,初学C#泛型的人,总是会被这个T搞得的糊里糊涂,但是我们细想一下: 加了一个T有什么用?
假如不加T的话,就是一个普通的方法,正是因为加了一个T,Swap<T>()才成为了泛型方法。有了这个T,泛型方法就有了它的存在的意义,通过类型参数T,给方法的参数(如ref T lhs,ref T rhs)和方法体里面的变量的定义(如T temp), 带来了极大的灵活性,并且是类型安全的。
既然是泛型方法,按照泛型的规定的话,肯定会有一个T啦,但这个T究竟加在哪里才最合适呢? 语言大师把它加在方法标示的后面,并且用尖括号括住,这样就是定义了一个泛型方法。初学者可能对这种声明的形式很反感,或者说看起來很不爽,我一开始就是这样,但后来想了想,假如编程大师把它放在方法标示的前面,如<T>Swap() 这样子,你会觉得怎样,好像也不怎么好看, 所以放在后面也不失合理性。
应用举例:
下面的代码示例演示一种使用 int 作为类型参数的方法调用方式:
也可以省略类型参数,编译器将推断出该参数。下面对 Swap 的调用等效于前面的调用:
相同的类型推断规则也适用于静态方法以及实例方法。编译器能够根据传入的方法参数推断类型参数;它无法仅从约束或返回值推断类型参数。因此,类型推断不适用于没有参数的方法。类型推断在编译时、编译器尝试解析任何重载方法签名之前进行。编译器向共享相同名称的所有泛型方法应用类型推断逻辑。在重载解析步骤中,编译器仅包括类型推断取得成功的那些泛型方法。在泛型类中,非泛型方法可以访问类级别类型参数,如下所示:
class SampleClass<T>{ void Swap(ref T lhs, ref T rhs) { }}
如果定义的泛型方法接受与包含类相同的类型参数,编译器将生成警告 CS0693,因为在方法范围内,为内部 T 提供的参数将隐藏为外部 T 提供的参数。除了类初始化时提供的类型参数之外,如果需要灵活调用具有类型参数的泛型类方法,请考虑为方法的类型参数提供其他标识符,如下面示例中的 GenericList2<T> 所示。class GenericList<T>
{
// CS0693
void SampleMethod<T>() { }
}
class GenericList2<T>
{
//No warning
void SampleMethod<U>() { }
}
使用约束对方法中的类型参数启用更专门的操作。此版本的 Swap<T> 现在称为 SwapIfGreater<T>,它只能与实现 IComparable<T> 的类型参数一起使用。
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
泛型方法可以使用许多类型参数进行重载。例如,下列方法可以全部存在于同一个类中:void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }
泛型方法是使用类型参数声明的方法,如下所示:
请看下面的泛型方法Swap<T>() ,初学C#泛型的人,总是会被这个T搞得的糊里糊涂,但是我们细想一下: 加了一个T有什么用?
假如不加T的话,就是一个普通的方法,正是因为加了一个T,Swap<T>()才成为了泛型方法。有了这个T,泛型方法就有了它的存在的意义,通过类型参数T,给方法的参数(如ref T lhs,ref T rhs)和方法体里面的变量的定义(如T temp), 带来了极大的灵活性,并且是类型安全的。
既然是泛型方法,按照泛型的规定的话,肯定会有一个T啦,但这个T究竟加在哪里才最合适呢? 语言大师把它加在方法标示的后面,并且用尖括号括住,这样就是定义了一个泛型方法。初学者可能对这种声明的形式很反感,或者说看起來很不爽,我一开始就是这样,但后来想了想,假如编程大师把它放在方法标示的前面,如<T>Swap() 这样子,你会觉得怎样,好像也不怎么好看, 所以放在后面也不失合理性。
应用举例:
static void Swap<T>(ref T lhs, ref T rhs) { T temp; temp = lhs; lhs = rhs; rhs = temp; }
下面的代码示例演示一种使用 int 作为类型参数的方法调用方式:
public static void TestSwap() { int a = 1; int b = 2; Swap<int>(ref a, ref b); System.Console.WriteLine(a + " " + b); }
也可以省略类型参数,编译器将推断出该参数。下面对 Swap 的调用等效于前面的调用:
Swap(ref a, ref b);
相同的类型推断规则也适用于静态方法以及实例方法。编译器能够根据传入的方法参数推断类型参数;它无法仅从约束或返回值推断类型参数。因此,类型推断不适用于没有参数的方法。类型推断在编译时、编译器尝试解析任何重载方法签名之前进行。编译器向共享相同名称的所有泛型方法应用类型推断逻辑。在重载解析步骤中,编译器仅包括类型推断取得成功的那些泛型方法。在泛型类中,非泛型方法可以访问类级别类型参数,如下所示:
class SampleClass<T>{ void Swap(ref T lhs, ref T rhs) { }}
如果定义的泛型方法接受与包含类相同的类型参数,编译器将生成警告 CS0693,因为在方法范围内,为内部 T 提供的参数将隐藏为外部 T 提供的参数。除了类初始化时提供的类型参数之外,如果需要灵活调用具有类型参数的泛型类方法,请考虑为方法的类型参数提供其他标识符,如下面示例中的 GenericList2<T> 所示。class GenericList<T>
{
// CS0693
void SampleMethod<T>() { }
}
class GenericList2<T>
{
//No warning
void SampleMethod<U>() { }
}
使用约束对方法中的类型参数启用更专门的操作。此版本的 Swap<T> 现在称为 SwapIfGreater<T>,它只能与实现 IComparable<T> 的类型参数一起使用。
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
泛型方法可以使用许多类型参数进行重载。例如,下列方法可以全部存在于同一个类中:void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }
相关文章推荐
- QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )
- 面向对象中多态和泛型的关系(可以解释为什么说 iterator方法中有多态存在 )
- R中面向对象编程方法(泛型、类解释)
- 自旋锁(spinlock) 解释得经典,透彻
- Java泛型:泛型类、泛型接口和泛型方法
- 对差分方程应用积分方法的解释
- 解释参数在方法中的传递过程
- 移花接木:当泛型方法遇上抽象类----我的“内存数据库”诞生记
- java JNI 实现原理 (五) JNI方法解释调用
- 靜態方法上的泛型
- 10个经典的 Java main 方法面试题
- AFNetwork 作用和使用方法具体解释
- Java基础-关于session的详细解释(经典)(二)
- 图像直方图及直方图均衡总结(一)经典方法(附matlab和opencv端算法实现)
- 关于Python的属性、参数、方法的解释、区别
- 【编程范式】汇编解释swap方法
- 自旋锁(spinlock) 解释得经典,透彻
- C#中泛型方法作用举例
- 数组、arraylist和list的区别和泛型的解释
- VB.Net 经典画圆方法