连载,LINQ兵法十四章,1(1of1)

hi20140509 2014-05-09 07:04:20
加精
上一篇

第一章 从类型到接口

先看一个简单的程序:
int x = 1;
object y = 2;
Console.WriteLine(x.GetType());
Console.WriteLine(y.GetType());


运行结果:
System.Int32
System.Int32

我们定义了两个变量,x和y,它们都是整数。

现在的问题是,int x和object x这两种定义究竟有什么不同。

我们利用VS的智能感知提示来观察下:

这是x的


这是y的


我们发现y只有4个方法,而x有6个。CompareTo和GetTypeCode对于y是没有的。

我们看下CompareTo方法的提示:



请注意,这个方法是属于int的(int.CompareTo)

同样是定义一个整数,int x和object y究竟有什么不同呢?

我们看object y,它是什么意思?

很多人不假思索地说,这还不简单?它表示定义了一个object类型的变量,y。请注意,这种说法是不准确的,object y的确切含义是,它定义了一个变量,这个变量可以是object类型,或者它的派生类型。我们知道,object是一切类型的基类(这一点和Java是一样的,在很多编程语言/类库中都是如此,比如CObject是MFC类型的基类,TObject是VCL的基类等等)。因此object y中的y可以是object,也可以是任意类型,比如string int double甚至是一个类的实例,比如User、Product 或者 ContactList。

int x呢,它只能是一个整数,因为整数类型没有派生的类型。它不能表示 string或者double了。所以,int x表示,x这个类型,编译器将其视作int,它可以调用int的方法,而object y编译器将其视作object,它可以是任意对象,但是编译器只能调用这写类型共同的基类,也就是object中定义的方法,而不能直接调用其某个派生类,比如int中的方法。

看这样一个程序:
class A
{
public void FooA() { }
}

class B : A
{
public void FooB() { }
}

class C : B
{
public void FooC() { }
}

class Program
{
static void Main(string[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}

C#的继承和定义方法的方式和C++、Java不同,但是读者应该不会觉得难以理解。

根据前面所述,A类型的变量a b c可以接受A类型和A类型的派生类型的对象实例,因此上面三行都是合法的。

但是

A d = new object();


这么写就是不合法的,A类型不能接受它的父类的类型。

同理,

B b = new A();


这么写也是不行的。

我们观察下我们定义的三个类型:







也许你认为b.敲出来以后应该能看到FooB,而c.敲出来能看到FooB和FooC,那么你就错了。我们之前说了,当你定义A类型的时候,无论接收的是什么类型的对象实例,编译器都视作是A类型,所以只能看到A类型的方法。

我们写
C d = new C();




此时就可以看到FooB和FooC了。

如果我们希望让c这个对象也能看到FooB和FooC,(它是A类型),我们需要让编译器将它“视作”C类型,因此用as运算符:

A c = new C();
(c as C).FooC();




此时可以看到FooC了。

看这样一个程序:

class A
{
public void SayHello()
{
Console.WriteLine("Hello A");
}
}

class B
{
public void SayHello()
{
Console.WriteLine("Hello B");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.SayHello();
B b = new B();
b.SayHello();
}
}


A和B是两个无继承关系的类,但是巧合的是,它们都有一个相同方法签名(指一个方法的方法名、参数和返回值都一样)的方法:SayHello。
我们的主程序分别调用了这两个方法。

我们有没有办法“取最小公倍数”呢。接口可以帮我们做到这一点。

我们可以定义一个接口:

interface ISayHello
{
void SayHello();
}


接口中包含了那个一致的方法。然后我们让这两个类都实现这个接口,相当于告诉编译器,它们都具有了这个接口定义的SayHello方法:

class A : ISayHello
{
public void SayHello()
{
Console.WriteLine("Hello A");
}
}

class B : ISayHello
{
public void SayHello()
{
Console.WriteLine("Hello B");
}
}


最后我们用接口类型替代具体的类型,调用它:

class Program
{
static void Main(string[] args)
{
ISayHello a = new A();
a.SayHello();
ISayHello b = new B();
b.SayHello();
}
}


我们回顾下:
ISayHello a = new A();


这到底是什么意思呢?ISayHello这个类型告诉编译器,将a“视作”任意具有ISayHello这个接口定义的类型方法的任意类的实例,它可以是A,也可以是B,或者C,只要C也实现了ISayHello。

回到最初的例子,int具有一个CompareTo的方法,它的作用是对当前的整数和传入的整数比较,并且将结果返回:
如果这个整数比传入的大,返回1,如果相等,返回0,如果小于传入的整数,返回-1

看如下程序:
int x = 1;
Console.WriteLine(x.CompareTo(10) < 0 ? "小于" : "大于等于");

运行结果

小于

其实,拥有CompareTo的并非只有int,string也有。它比较的是字符串的ascii的大小,如果一个字符串有多个字符,那么优先比较第一个字符,如果相等,再比较第二个。通俗地说,你翻开一本英文字典,排在前面的单词比排在后面的更小。
string y = "b";
Console.WriteLine(y.CompareTo("a") < 0 ? "小于" : "大于等于");

因此这个程序输出

大于等于

我们怎么将这两个程序用接口来改写呢?很显然,只要找到一个接口,包含CompareTo这个方法的定义就可以。幸好int string都实现了IComparable接口,并且包含一个int CompareTo(object)的方法。我们来调用它:

IComparable x = 1;
Console.WriteLine(x.CompareTo(10) < 0 ? "小于" : "大于");
IComparable y = "b";
Console.WriteLine(y.CompareTo("a") < 0 ? "小于" : "大于");


程序的结果和刚才一样。

请注意,我们先前调用的int.CompareTo的方法签名是int CompareTo(int),并非int CompareTo(object),string的也一样,严格来说,这样的改写其实是不等价的。但是在这里,我们不深入探讨这一点。大体上说,我们使用接口代替了具体的类型完成了改写。

下一篇
...全文
2324 33 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
gucangen 2014-08-22
  • 打赏
  • 举报
回复
温瑞安 2014-07-16
  • 打赏
  • 举报
回复
mark,有时间学习。
zouzouol 2014-06-10
  • 打赏
  • 举报
回复
先关注下,有时间了马上看,赞一个
oTerminator12 2014-05-25
  • 打赏
  • 举报
回复
不错,
直面人生 2014-05-24
  • 打赏
  • 举报
回复
学习学习~~~
leujunbao 2014-05-18
  • 打赏
  • 举报
回复
引用 1 楼 wizardforcel 的回复:
第二句实际上是在栈上创建一个临时int变量 值为2 然后装箱赋给y ide显示的方法是形式类型拥有的方法 但是反射获取到的是实际类型
+1
wbz2cdma 2014-05-17
  • 打赏
  • 举报
回复
写得真不错,坚持!
X_Craft 2014-05-15
  • 打赏
  • 举报
回复
好贴一定要顶
shizhenkun001 2014-05-15
  • 打赏
  • 举报
回复
好东西啊,楼主辛苦
慧眼识狗熊 2014-05-14
  • 打赏
  • 举报
回复
mark
猴头 2014-05-13
  • 打赏
  • 举报
回复
网络菜鸟00 2014-05-12
  • 打赏
  • 举报
回复
不能不支持,感谢LZ分享!!
MCTKing4 2014-05-12
  • 打赏
  • 举报
回复
很不错的一个贴
joyhen 2014-05-12
  • 打赏
  • 举报
回复
讲解细致,不错
树影重重 2014-05-12
  • 打赏
  • 举报
回复
引用 6 楼 x_wy46 的回复:
支持楼主,学习!
+1
踏平扶桑 2014-05-12
  • 打赏
  • 举报
回复
收藏了。多谢分享
BenBenBears 2014-05-12
  • 打赏
  • 举报
回复
且读且珍惜
Ahoo 2014-05-12
  • 打赏
  • 举报
回复
yyf1229 2014-05-12
  • 打赏
  • 举报
回复
多谢分享
xiaocongzhi 2014-05-11
  • 打赏
  • 举报
回复
加载更多回复(8)

111,088

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧