您的位置:首页 > 其它

泛型方法经典解释

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() 这样子,你会觉得怎样,好像也不怎么好看, 所以放在后面也不失合理性。

应用举例:

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>() { }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: