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

ASP.NET
赫赫大名的A*寻路算法(vb.net版本)
asp.net(c#)下Jmai去说明 使用与下载
[原创]完美解决Could not load file or assembly ''AjaxPro.2'' or one of its dependencies. 拒绝访问。
asp.net下gridview 批量删除的实现方法
用CSS实现图片倾斜 只支持IE
.net get set用法小结
vs 不显示行号的操作方法
ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)
ASP.Net不执行问题一解
asp.net 无限分类
让VS2008对JQuery语法的智能感知更完美一点
扩展方法ToJSON() and ParseJSON()
asp.net下PageMethods使用技巧
Linq to SQL Delete时遇到问题的解决方法
实现ASP.NET多文件上传程序代码
ASP.NET AJAX 1.0 RC开发10分钟图解
asp.net get set用法
ASP.NET下使用WScript.Shell执行命令
asp.net2.0实现邮件发送(测试成功)
Asp.net 无限级分类实例代码

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-01-04   浏览: 358 ::
收藏到网摘: 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中是完全一样的。