当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > C#3.0教程:自动属性和扩展方法

ASP.NET
asp.net Server.MapPath方法注意事项
asp.net下常用的加密算法MD5、SHA-1应用代码
几个 ASP.NET 小技巧
ASP.NET内置对象之Application对象
ASP.NET使用正则表达式屏蔽垃圾信息
asp.net“服务器应用程序不可用” 解决方法
asp.net Linq把数据导出到Excel的代码
asp.net ext treepanel 动态加载XML的实现方法
silverlight2.0Beta版TextBox输入中文解决方法
asp.net转出json格式客户端显示时间
asp.net下Linq To Sql注意事项小结
ASP.NET动态加载用户控件的实现方法
asp.net web大文件上传带进度条实例代码
asp.net DZ论坛中根据IP地址取得所在地的代码
向asp.Net进发 数据库连接操作
.net 上传文件前所未有的简单
asp.net gridview代码绑定
asp.net中List的使用方法
Asp.net(C#)实现验证码功能代码
asp.NET开发中正则表达式中BUG分析

ASP.NET 中的 C#3.0教程:自动属性和扩展方法


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-01-04   浏览: 456 ::
收藏到网摘: n/a

使用自动属性后,你可以不用手工声明一个私有成员变量以及编写get/set逻辑,取而代之的是,编译器会自动为你生成一个私有变量和默认的get/set 操作。系统为你产生的私有变量在IDE中,你是看不到的,如下图:

 

当然如果你希望属性中有些赋值或者取值逻辑校验,自动属性可是不适合你的。

上面的代码我们编译后,再用 Reflector 反编译后,我们可以看到上述代码中的属性变成了如下代码:这个编译器给我们产生的私有变量,显然不是那么容易重名的。


[CompilerGenerated]
private string <>k__AutomaticallyGeneratedPropertyField0;

public string Name
{
[CompilerGenerated]
get
{
return this.<>k__AutomaticallyGeneratedPropertyField0;

}
[CompilerGenerated]
set
{
this.<>k__AutomaticallyGeneratedPropertyField0 = value;
}
}

注意:如果你只希望属性有 get 或者 set 方法,这些情况都是无法使用 自动属性的,需要你自己来书写。否则就会报如下的错误:

'ConsoleApplication1.MyClass.Name.set' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

但是 get 和 set 访问级别不一样,比如一个是 public,一个是 internal,则可以书写成下述方式,而不会报错误。

public int ID { get; internal set; }

今天早上在MSDN站点看到这样一篇文章: C# 3.0 LINQ 的演变及其对 C# 设计的影响 。 从这篇文章我们就可以明显的看到,C# 3.0 所新增的这些特性,可以认为都是为了LINQ 的发展,为了LINQ更易用,所创建的一些新特性,当然这些新特性也可以被非LINQ相关功能所使用。LINQ的发展,带动了C#3.0 这一系列新特性的产生。

回来说我们的话题,扩展方法,首先看一个最简单的代码例子:

扩展方法的定义,需要注意三个部分:1、静态类(私有公共都可以);2、静态方法(私有公共都可以);3、第一个函数参数前带 this(必须是第一参数前)

namespace Hongjun.Guo
{
static class MyExtensionMethods
{
internal static void Print(this object s)
{
Console.WriteLine(s);
}
}
}

扩展方法的使用,需要注意点: using 你定义所在的命名空间。


using Hongjun.Guo;

static void Main(string[] args)
{
object o = "dsdgs";
o.Print();
}

这样一个简简单单的代码后,我们就可以很方便的对一些不开源的第三方控件增加很多我们自己额外需要的功能。

扩展方法的使用,有时候并不是这么简简单单,我们来看一些特殊情况,通过这些特殊情况的分析,我们可以更深入的了解扩展方法:

情况一 : 扩展方法跟原来类的方法重名时候的处理逻辑。

场景:我们是对一个第三方的没有开放源代码组件的一个类扩展了一个方法,比如方法: Print 。过了一段时间后,这个第三方的组件发布了新版本,该类的增加了 Print 方法。这时候会出何种效果??

问题演示代码:


namespace Hongjun.Guo
{

public class MyClass
{
public void Print()
{
Console.WriteLine("****");
}
}

static class MyExtensionMethods
{
internal static void Print(this MyClass s)
{
Console.WriteLine("haha " + s.ToString());
}

}

}

调用范例:


using Hongjun.Guo;

static void Main(string[] args)
{
MyClass o = new MyClass();
o.Print();

Console.ReadLine();
}

这时候我们会看到何种结果呢??

答案:看到的是 ****

也就是,扩展方法跟类的方法冲突时候,编译使用不会报任何错误,这时候以类的方法优先级最高,这时我们使用类的方法,而不是扩展方法。

分析:

我们把上述两组代码编译后,再反编译成IL,我们就可以看到,实际上,扩展方法在IL层上是不存在的。

扩展方法实际是编译器调用某个类的某个方法的时候,先去这个类找,如果有这个方法,则就调用;如果找不到,根据引用的命名空间,再去找扩展方法(静态类的静态方法)。找到,就使用,找不到当然就编译错误了。

根据这个分析结果,我们就可以理解上述问题处理的结果了。

情况二: 扩展方法的嵌套

比如我们有如下扩展方法。


namespace Hongjun.Guo
{
static class MyExtensionMethods
{
public static int Test01(this int i)
{
return i * 3;
}

public static int Test02(this int i)
{
return i + 5;
}
}
}

下面是调用范例:


static void Main(string[] args)
{
int mm = 7;
Console.WriteLine(mm.Test01().Test02());
Console.WriteLine("*****");
Console.WriteLine(mm.Test02().Test01());

Console.WriteLine("*****");

Console.WriteLine(MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm)));


Console.ReadLine();
}

问,调用的显示结果是何值?

答案: 依次显示: 26,36,26

分析:

mm.Test01().Test02()

这行代码编译后相当于如下代码:

MyExtensionMethods.Test02(MyExtensionMethods.Test01(mm))

这两行代码在编译后的IL中是完全一样的。