看了包建强同学的“关于反射技术”及大家的评论。觉得博客园该进行改革了。

重构吧~~还有什么好说的呢?

需求:
基本原则:  设置积分或者权限,只有积分或者权限达到一定程度,才能直接在首页精华区发文章。比如老赵,包建强同学等,这些大家公认的大牛,是可以直接在首页精华区发表文章的。其他积分或权限达不到的,只能在首页候选区发。

实施细则:

Class Cnblog
{
     List
<牛人> 评审组
     
// 有博客园管理员和群众评选
     public Cnblog()
      {
        
        
        评审组 
= new List<牛人>();
        
        评审组.Add (
new 牛人(微软MVP拥有直接在首页精华区发文章的权限));
        
        评审组.Add (
new 牛人(所发的博客到达一定数量,且能够自成体系的博主,可以有在首页精华区发文章的权限;));
        
      }

      
public void ShowBlog()
      {
         
if (有权限)
         {
             直接显示在首页精华区;
             
return;
         }
            
         
else
         {
            放在首页候选区;
            Adjust();
            ShowBlog();
         }
      }
      
      
private void Adjust()
      {
          
if (IsGood())
            积分或权限 
+= 10

          
else if (IsBad())
            积分或权限 
-= 10
          
else
            积分活权限
++;
      }
       
      
private bool IsGood()
      {
           
return Review() > 评审.Count/2 ;
      }
      
      
private bool IsBad()
      {
           
// 如果没有评审组的人看,就默认为不坏。
           return Review() <= 评审.Count/2 && Review() > 0 ;
      }

      
private int Review()
      {
         
int goodCount = 0;
          
foreach(var 牛人 in 评审组)
          {
              
if(牛人.评审() == Good)
                 goodCount 
++;
          }
              
      }
}

当然,代码还有不足。总体思路是这样的。

其实,说句实在话,吉日兄的文章实在让我看的很失望,每次抱着很大的希望进去,发现什么都没有讲。可能他有他的想法吧,我没有体会罢了。

我不支持谁,我只希望博客园能给我们所有.net爱好者和靠.net吃饭的人一个汲取营养,证明自己的地方。

PS.
这是我第一次往首页上发。希望大家不要介意,以后不会了。我实在不喜欢看到博客园吵吵闹闹的。博客园,应该更像一个深山幽湖旁的一个大宅院。薄雾缭绕,绿竹环绕,里面居住的世外高人。每个人进来的时候,在被这份宁静和悠远所征服,又能从高人那里得到自己想要的“武功”。
posted @ 2009-10-16 19:49 麦穗 阅读(1498) 评论(43) 编辑

常用SQL语句



1、用什么的SQL语句来查的一个表中有相同的记录条数

select 相同条件的字段,count(*) from 表
group by 相同条件的字段
having count(*) >1

2、请问怎么查看数据库服务器IP地址

--得到服务器的IP地址

create table #ip(id int identity(1,1),re varchar(200))

declare @s varchar(1000)
set @s='ping '+left(@@servername,charindex('\',@@servername+'\')-1)+' -a -n 1 -l 1'
insert #ip(re) exec master..xp_cmdshell @s

select 服务器名=@@servername,IP地址=stuff(left(re,charindex(']',re)-1),1,charindex('[',re),')
from #ip
where id=2

drop table #ip

3、日期字段怎么只保存年月日,而不要时间?

CONVERT (varchar(10), Date, 112))

4、如何删除一个数据库?

if exists (select * from sysdatabases where name = 'dba')
drop database dba
GO

5、如何用SQL语句创建一个自动编号的字段?

create table mytable(
id int identity(1,1)
)

6、没有这样的sql语句,可以取从第x条到第y条的数据集?

查询第X页,每页Y条记录

最基本的处理方法(原理):

如果表中有主键(记录不重复的字段也可以),可以用类似下面的方法,当然y,(x-1)*y要换成具体的数字,不能用变量:

select top y * from 表 where 主键 not in(select top (x-1)*y 主键 from 表)

如果表中无主键,可以用临时表,加标识字段解决.这里的x,y可以用变量.

select id=identity(int,1,1),* into #tb from 表
select * from #tb where id between (x-1)*y and x*y-1

7、SQLServer中 如何取出一个表的所有列名?
方法如下:先从SYSTEMOBJECT系统表中取得数据表的SYSTEMID,然后再SYSCOLUMN表中取得该数据表的所有列名。 
SQL语句如下:

declare @objid int,@objname char(40)
set @objname = 'tablename'
select @objid = id from sysobjects where id = object_id(@objname)
select 'Column_name' = name from syscolumns where id = @objid order by colid

8、用什么查询语句或函数可以知道是否存在一个数据库

if db_id(N'要检查的库名') is null
print '数据库不存在'
else 
print '数据库存在'

9、删除一个数据表

if exists(select * from sysobjects where name='要删除的表名' and xtype='u')
Drop table 表名
go

10、SQL语句 两种求和
第一个:一行记录中 如何求 字段1 字段2 字段3 字段N 的和?

select column1+column2+......+column3 as 'totalnum' From Tablename

第二个:一列记录中 如何求 本字段所有记录 的和?

Select sum(字段名) From TableName

字段属性是数字(数值型、货币型都可)的时候才可以实现,如果有NULL值则被忽略。
posted @ 2009-10-14 17:20 麦穗 阅读(202) 评论(0) 编辑

转自http://blog.163.com/2sws/blog/static/1791024920098434529583/

1、命名约定

Pascal和Camel命名约定

编程的命名方式主要有Pascal和Camel两种(Pascal:每个单词的首字母大写,例如ProductType;Camel:首个单词的首字母小写,其余单词的首字母大写,例如productType)


以下是一些常用的C#成员及其推荐命名方法:

标志符

规则

实例与描述

类class

Pascal

Application

枚举类型enum

Pascal

记住,是以Pascal命名,切勿包含Enum,否则FXCop会抛出Issue

委托delegate

Pascal

以Pascal命名,不以任何特殊字符串区别于类名、函数名

常量const

全部大写

全部大写,单词间以下划线隔开

接口interface

Pascal

IDisposable 注:总是以 I 前缀开始,后接Pascal命名

方法function

Pascal

ToString

命名空间namespace

Pascal

以.分隔,当每一个限定词均为Pascal命名方式,比如:

using ExcelQuicker.Framework

参数

Camel

首字母小写

局部变量

Camel

也可以加入类型标识符,比如对于System.String类型,声明变量是以str开头,string strSQL = string.Empty;

数据成员

Camel

以m开头+Pascal命名规则,如mProductType(m意味member)

属性

Pascal


1.1、局部变量命名

在primitive的局部变量命名时,使用Camel命名规则,

比如:int type = 0;

double count = 0;

对于string类型定义,通常使用str前缀+Pascal命名的方式,

比如string strSql = ""; //这是一种典型的命名SQL语句字符串的方式。

而对于此外的类型对象定义,通常的做法是使用obj前缀+Pascal命名的方式,来告知我们这个变量是一个对象。或者也可以直接使用类名的Camel命名规则。

比如:Application objApplication = new Application();
            Application application = new Application();

1.2、参数命名

Camel命名规则,首字母小写

1.3、类数据成员/属性命名

数据成员命名以Camel命名方式,而属性以Pascal命名。通常如果数据成员与属性成对的话,数据成员与属性的命名区别仅在于变量名的第一个字母是小写还是大写。

比如

class Appcalition

{

        private ArrayList worksheetCollection = new ArrayList();

        public ArrayList WorksheetCollection

        {

            get

            {

                return this.worksheetCollection;

            }

        }

}

另外,类的成员数据/方法调用时,应该加上this限定符,this在编辑环境中是蓝色的,更利于我们区分局部变量、参数或静态变量,并且利于FXCop检测区分。(如果使用FxCop扫描和检测代码的话)

1.4、命名空间命名

在dot之间的各限定字符串符合Pascal格式

1.5、委托缩写

委托的命名方式我常常以Pascal命名,并且在命名的后面加EventHandler

比如public delegate void MouseEventHandler (object sender, MouseEventArgs e);    //用于处理与鼠标相关的事件或委托

对于自定义的委托,其参数第一个建议仍然使用object sender,sender代表触发这个时间或委托的源对象。而第二个参数继承于EventArgs类,并且在派生类中实现自己的业务逻辑。

1.6、自定义异常类

自定义异常类以Exception结尾,并且在类名中能清楚的描述出该异常的原因。比如NotFoundFileException,描述出了某个实体(文件、内存区域等)无法被找到。

1.7、枚举

枚举的命名是Pascal命名,不需要在枚举中加入Enum,枚举的名称能清楚的表明该枚举的用途。

1.8、常量命名

全部大写,单词间并且以下划线间隔,如public const int LOCK_SECONDS = 3000; 虽然在MSDN中常量的命名推荐使用Pascal,但是从C++沿袭的命名规则来看,将常量全部大写更加能清楚的表示常量与普通变量之间的区别。

1.9、命名缩写

在 一般情况下,不推荐缩写命名,不要担心变量命名长,长的变量名能使变量的意义更加清晰,其实从长变量名的负面作用三,因为Ctrl+C和Ctrl+V加上 在VS中的智能感知,其负面追用已经很小。变量命名的原则是,尽最大努力让其他人在看到我们的变量/函数/…等的第一时间,大概能猜出它是做什么的。

比如:int productTypeCount = 0; //我们在第一时间就能知道它是记录产品的数量的变量

而 对于糟糕的命名方式:int prodTypeCount = 0; //它是productTypeCount的简写,我们一部分人也许知道prod是product的缩写,但是每人能保证所有的人都知道它。我个人认为: 最优秀的代码它本身就是注释。作为一流的程序员。并不仅仅实现功能,而是要让我们的代码更加优美,具备让他人维护或今后扩充的能力。作为现在的业务系统, 其门槛的准入水平已大大降低,实现功能上的需求已没有什么难度,但是高手和菜鸟的区别在于,高手的代码通俗易懂,在整个编码的过程中,不仅能考虑到性能、 还会考虑代码可读性和维护性。

1.10、数据库命名

数据库的字段、表名的命名都推荐采用Pascal命名方式,尽量不采 用缩写。当然,使用长的字段名、表名,可能会使SQL语句的编写带来负面影响。我推荐大家可以使用一些ORM,ORM的性能肯定不会比直接写SQL的好, 但是如果做业务系统,更重要的是系统多久能交付用户使用,ORM不仅使开发时间可以缩短不少,并且在后期的维护上也比直接写SQL便利很多。

2、注释规范

2.1、文件头部注释

在 代码文件的头部进行注释,这样做的好处在于,我们能对代码文件做变更跟踪。在代码头部分标注出创始人、创始时间、修改人、修改时间、代码的功能,这在团队 开发中必不可少,它们可以使后来维护/修改的同伴在遇到问题时,在第一时间知道他应该向谁去寻求帮助,并且知道这个文件经历了多少次迭代、经历了多少个程 序员的开发和修改。

样本:

/********************************************************************************

** 作者: Eunge

** 创始时间: 2004-6-8

** 修改人:Lucy

** 修改时间:2004-12-9

** 修改人:Lucy

** 修改时间:2005-01-29

** 描述:

**    主要用于产品信息的资料录入,…

*********************************************************************************/

2.2、函数、属性、类等注释

请 使用///三斜线注释,这种注释是基于XML的,不仅能导出XML制作帮助文档,而且在各个函数、属性、类等的使用中,编辑环境会自动带出注释,方便你的 开发。以protected,protected Internal,public声明的定义注释都建议以这样命名方法。

例如:

/// <summary>

/// 用于从ERP系统中捞出产品信息的类

/// </summary>

class ProductTypeCollector

{

       …

}

2.3、逻辑点注释

在 我们认为逻辑性较强的地方加入注释,说明这段程序的逻辑是怎样的,以方便我们自己后来的理解以及其他人的理解,并且这样还可以在一定程度上排除BUG。在 注释中写明我们的逻辑思想,对照程序,判断程序是否符合我们的初衷,如果不是,则我们应该仔细思考耀修改的是注释还是程序了…

3、排版

我的排版原则与建议:

1、 每行语句至少占一行,如果语句过长(超过一屏),则该语句断为两行显示;

2、 把相似的内容放在一起,比如数据成员、属性、方法、事件等,并适当的使用#region…#endregion,我最喜欢把机器生成的代码都放在一 个#region里面,比如在编写ASP.NET程序时,对应自动产生的控件定义,我常用#region Automatic Generated Web Components … #endregion把他们框住

3、 使用空格,

(1)       双目操作符的前后加空格(+, =, && 等),index = index + 1;

(2)       单目操作符前加空格(!, ++, ~ 等), index ++;

(3)       逗号、分号只在后面加空格

4、 使用空行,在一段功能代码、或者函数、属性之间插入空行,这样会很直观。

在Visual Studio 2005中,其实已经带有代码格式化这样的功能,快捷键是Ctrl+K -> Ctrl+D。

4、界面控件命名

我 的建议是使用默认控件名作为前缀,前缀名称全部小写,这样的好处是不必为未知的控件统一命名方式发愁,比如对于Label标签控件,有的人用缩写lbl, 有的人用lab,有的人用lb。这样其实仍然是避免使用缩写,有的时候仍然会使命名变得冗长,但是命名更加能反应出变量的意义,并且各个开发人员也能更好 的执行,因为他们不需要去背记各个变量的缩写。

protected System.Web.UI.WebControls.Button buttonQuery;

protected System.Web.UI.WebControls.DropDownList dropdownlistProductType;

protected System.Web.UI.WebControls.TextBox textboxManufactureDate;

5、代码可读性一些建议

(1)注意运算符的优先级,我们应该尽量使用括号明确表达式的操作顺序,避免使用默认优先级,给我们以及维护人带来困扰

(2)避免使用不易理解的数字,用有意义的标识来替代(枚举和常量)

比如:

if(productType == 0)

       …

else if (productType == 1)

       …

(不推荐使用)

if(productType == ProductType.CD)

       …

else if (productType == ProductType.DVD)

       …

(推荐使用)

(3)在界面层中尽量使用异常处理try语句,不要将系统级别的错误直接暴露给用户,而更应该的是把系统抛出的错误信息记录到LOG日志文件中去,告诉用户友好的提示信息

在Visual Studio 2005里面,有代码布局格式化功能,蛮有用的。其实代码的规范是为了使系统具有整体一致的编码风格,以使后期维护人员能更快的读懂代码并进行维护。我认 为代码规范有其必要性,但不能因为规范而规范,从开发而言,开发是为了更快的做出稳定的系统,而稳定的系统是为了给公司带来受益。开发人员、项目管理人员 都应该更多的从项目经营的角度出来,同时站在公司、客户的角度考虑问题,而不是因为代码而代码。

posted @ 2009-10-14 11:17 麦穗 阅读(141) 评论(0) 编辑
 我前天(是前天吧?应该是吧)写了一篇文章 “关于string的一个问题 ”。 OC Life 同学给我提了很好的建议。我研究了一下 Andytao的 “ [你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考”。 感觉之前的那篇文章可以忽略不计了。哎~~~自己怎么这么笨呢。

查MSDN,发现有这么一段话(其实Andytao的文章里也有,只不过我先看到MSDN,后来在看到了他的话,嘿嘿)
“The common language runtime automatically maintains a table, called the "intern pool", which contains a single instance of each unique literal string constant declared in a program, as well as any unique instance of String you add programmatically.

The intern pool conserves string storage. If you assign a literal string constant to several variables, each variable is set to reference the same constant in the intern pool instead of referencing several different instances of String that have identical values.”

就是说,在内存中,CLR维护一个驻留池,将字符串存放到里面。当给一个变量分配字符串的时候,CLR先到驻留池里找,如果找到了,就将该字符串的引用给这个变量,如果没有,就将该字符串创建到驻留池里,然后在将引用给该变量。 这就是为什么string s1 = "abc"; string s2 = "abc"; s1的指针=s2的指针了。


创建的时候,应该是在compile时创建的。 所以动态创建的字符串在第一次使用时,调用string.IsIntern这个方法时,得到的是空。 比如

string s1 = "ab"; s1+= "c" ;

string.IsIntern(s1) 是=空的。


但是如果

string s1 = "ab"; s1+= "c" ;string s2 = "abc";

则string.IsIntern(s1)  就= "abc"了。因为,在编译的时候 “string s2 = "abc";” 被CLR写进intern pool了。


再次感谢oc life!



posted @ 2009-10-14 09:52 麦穗 阅读(54) 评论(0) 编辑
请参见这篇文章 “Re: 关于string的一个问题

C#中的string类型比较特殊
  1) 它是Immutable的,即不可改变的(虽然也有别的方法可以改变,可参见也说C#中的Immutable)。
  2) 它重载了运算符“==” ,实现了str1 == str2的值比较,而不是引用的比较。
  3) 它本身却又是引用类型。

今天遇到一个问题。先看代码
Code

结果是什么? True or false?

大家都知道,.net的引用类型,其实每一个实例都是一个类的引用,在堆上分配不同的地址。因此,比如 ClassA instance1 = new ClassA(); ClassA instance2 = new ClassA(); 其实指向的是两个不同的内存地址。因此,object.ReferenceEquals(instance1, instance2)返回的应该是false。

但是,上面代码却返回的True。有点抽象。既然是True,就证明它引用的是同一个对象。那么,指向的内存地址应该是一样的了。好,为了证明以上推论,我写了下面的代码
Verify two string instance reference the same address

结果跟预料的一样,返回的是True。

我在网上找到这么一段话:
“In C# strings are reference types. However, operator==() is overloaded for strings and compares string contents, not reference equality. String.Equals() also compares string contents. What makes strings unique is that string literals are pooled. For instance, if we have the following code:

string s1 = "abc";
string s2 = "abc";
bool result = Object.ReferenceEquals(s1,s2);

the value of result will be true. ReferenceEquals() is not lying here. s1 and s2 indeed reference the same object. The sysetm recognized that we have two equivalent string literals, and merged them into one. It can get away with it, because string objects are immutable. This check for duplicate string literals occurs when you code is JIT-compiled, i.e. converted from IL (intermediate language) to native (x86) machine codes. Thus, string literals are merged even when they are from different assemblies.Note, however, that merging process affects only string literals”。

也就是说,系统把两个string 对象合并成一个了。

这样的好处,我想可能是避免在代码中给string 对象赋予相同值得时候,在heap上重复创建对象(尤其在循环中)所造成的性能损失吧。
posted @ 2009-10-12 16:46 麦穗 阅读(89) 评论(2) 编辑
 

参考 : 不能不说的C#特性-匿名方法和Lambda表达式 (横刀天笑)
     
我的C# 3.0之新特性学习笔记(2) (Jimmypony)
     
      嘻嘻,两位没意见吧?

定义:

           匿名方法 顾名思义,就是没有方法名的方法。

             Lambda 表达式,其实就是匿名方法的另一种形式,其格式为 :参数列表 => 表达式/语句块。

理解:

1) 何为参数列表。此参数列表跟一个普通的函数的参数列表时一样的。

2) 何时用匿名方法和Lambda表达式

A.      需要一个临时方法,该方法只是用一次或者使用很少几次。

B.      方法体很短,以至于声明也很短。

实现

 

铛铛铛铛,各位看官,这次我们来讲的是匿名方法和Lambda表达式。不是很难,写出来的代码也很优雅。首先,我们来看没有匿名方法的时代。

 

Case Scenario: 当一个事件被触发的时候,进行数据绑定。

我们有一个DataBind() 方法,如下

static void DataBind()

        {

            // To do

 

            Console.WriteLine("DataBinding");

        }

 

我们有一个叫RefreshButton的类,它有一个属性是 Name, 当它的Name改变的时候,会触发NameChanged事件。来看下面代码

    class RefreshButton

    {

        public event EventHandler NameChanged;

 

        protected virtual void OnNameChanged(EventArgs e)

        {

            if (NameChanged != null)

            {

                NameChanged(this, e);

            }

        }

 

        string name;

 

        public string Name

        {

            get { return name; }

            set

            {

                if (name != value)

                {

                    name = value;

                    OnNameChanged(new EventArgs());

                }

            }

        }

    }

 

好了,我们要在main方法里给NameChanged事件加一个方法

Dot Net 2.0 时代

static void Main(string[] args)

{

    RefreshButton btnRefresh = new RefreshButton();

 

    // In 2.0

    btnRefresh.NameChanged += new EventHandler(btnRefresh_NameChanged);

 

    btnRefresh.Name = "Refresh";

 

    Console.ReadKey();

}

 

static void btnRefresh_NameChanged(object sender, EventArgs e)

{

    DataBind();

}

 

2.0时代,我们要自己定义一个方法,在给它加上,无形中增加了很多敲代码的时间。当然,VS2005/2008有智能感知能力,但是从代码可读性来看,也不是非常满意。当读到 btnRefresh_NameChanged方法时,你可能还需要看看它的具体实现,来回跳来跳去很麻烦。

Dot Net 3.0时代

        static void Main(string[] args)

        {

            RefreshButton btnRefresh = new RefreshButton();

 

            // In 2.0

            //btnRefresh.NameChanged += new EventHandler(btnRefresh_NameChanged);

 

            // In 3.0

            btnRefresh.NameChanged += delegate(Object sender, EventArgs e)

            { DataBind(); };

 

            btnRefresh.Name = "Refresh";

 

            Console.ReadKey();

        }

 

OK 了,看少了什么?“static void btnRefresh_NameChanged(object sender, EventArgs e) 这个方法没有了。直接在上面了。“btnRefresh.NameChanged += delegate(Object sender, EventArgs e){ DataBind(); }; 这样代码量少了,同时,思路也看的清晰了。

 

在看Lambda表达式怎么写这个

 

        static void Main(string[] args)

        {

            RefreshButton btnRefresh = new RefreshButton();

 

            // Lambda Express

            btnRefresh.NameChanged += (sender, e) => { DataBind(); };

 

            btnRefresh.Name = "Refresh";

           

 

            Console.ReadKey();

        }

 

又少了些东东吧?参数列表(sender, e=> 表达式(DataBind(),Lamda表达式的标准结构。

 

其实匿名方法跟Lambda表达式都是一样的,只不过写的方式不同罢了。可以用Ildasm看一下就知道了,他们都会转化成一个“AnonymousMethod.Program::'CS$<>9__CachedAnonymousMethodDelegate1'”。

 

只不过Lambda表达式比匿名方法有更好的可读性。

 

下面重点说一下Lambda表达式的写法:

  1. 当输入参数为空时,左边的括号是不能省略的,比如

 

() => Console.WriteLine("This is a null parameters lambda expression");

 

  1. 当语句为一条的时候,可以不用加大括号,比如

(a,b) => Console.WriteLine("This is a null parameters lambda expression");

 

  1. 带返回值得,如输入a, b,返回a+b这类的,比如

(a, b) => {return a + b};

 

  1. 多个表达式用{}来括起来。比如

            btnRefresh.NameChanged += (sender, e) =>

            {

               if (e != null)

                    Console.WriteLine(e.ToString());

 

                DataBind();

            };

 

 

注意事项(都是个人观点哟):

 

1. 当表达式较短的时候,且该方法很少再被别的方法或者类调用的时候,才使用。如果表达式很长,那么用Lambda反而给人很邋遢的感觉。

2. 匿名方法和lambda表达式一般只用于替换委托方法的。单独定义方法的时候,这个是不可用的。

 

 

~~~又写好一篇。呵呵,这些都是为了下一个比较NBfeature做准备,它是谁呢?且听下回分解。。。

posted @ 2009-09-27 14:04 麦穗 阅读(104) 评论(0) 编辑


定义:

扩展方法允许对现存已编译的类型(例如 类,结构,接口)在不需要直接更新的情况下进行方法的扩展。

理解:

1) 扩展方法是对已编译类型的扩展。何为已编译类型? 说通俗点就是已经编译好的DLL或者exe

2) 扩展方法不需要直接更新已编译类型。一般来说,一个已编译好的DLL,你是不知道它的具体实现的,只是在引用它以后,能知道它的public方法 (用Reflector查看代码除外)。当你需要针对某个已引用的DLL在自己的项目中进行扩展,怎么办。扩展方法就是解决这类问题的。

3) 扩展方法是对方法的扩展。换而言之,它不是对已编译类型的扩展。通俗点就是给已编译的类型增加一些方法。

4) 扩展方法不仅可以给某个类增加方法,还可以给结构,接口增加方法。有人可能觉得我给一个类增加方法的话可以使用继承。可以,没有问题。但是如果遇到seal ed class怎么办呢?

好了,啰嗦了一堆,大家肯定等急了吧。赶快来看咋用的吧。

 

实现

 

1.       扩展方法 ---

 

比如,我们需要给string类型加一个扩展方法,用来将string转化成int 数组。嘻嘻,熟悉string的同学们都知道,string本身并没有一个方法来直接转化成一个数组。 好了,开工了,请看下面的代码:

namespace ExtensionMethod

{

    public static class ExtensionForClass

    {

        public static int[] ToIntArray(this string str)

        {

            // To do

        }

    }

}

 

 铛铛铛铛~~ 神奇的事情发生了,当你在你的项目中引用ExtensionMethod 命名空间,在一个string变量后面点“.”,你就会发现一个ToIntArray()的方法。见下图

 

看见了吧。好神奇闹~~~.在此时,我们默认的数组分隔符是“,”,如果分隔符不定,那么我们可以重载此扩展方法,如下

namespace ExtensionMethod

{

    public static class ExtensionForClass

    {

        public static int[] ToIntArray(this string str)

        {

            // To do

 

            return default(int[]);

        }

        /// <summary>

        /// Overload extension method ToIntArray

        /// </summary>

        /// <param name="str">source string</param>

        /// <param name="separator">Separator</param>

        /// <returns>Int Array</returns>

        public static int[] ToIntArray(this string str, char separator)

        {

            // To do

 

            return default(int[]);

        }

    }

}

 

恩, 搜噶,这样,我们就可以看到该方法的2个重载了,如下图

 

 

  1. 扩展方法 --- 结构

结构,结构??恩~~.net类库里现成的结构是啥呢?哦,对了,DateTime (别说你到现在还以为它是一个类哈)。比如说,有些数据库设计来说,把DateTime存成一个int的数,这样,在查找的时候,效率会很高,当然了,比较int要比比较DateTime要快呢。那么,我们在前台代码处理的时候,给DateTime加一个扩展方法,让它直接转化成Int。不多说废话,看下面代码

namespace ExtensionMethod

{

    public static class ExtentionForStruct

    {

        public static int ToInt(this DateTime dateTime)

        {

            // To do;

        }

    }

}

 

奇迹再次发生,如下图:

瞧见了吗?嘿嘿。

  1. 扩展方法 --- 接口

扩展接口?这是个令人深思的话题,先不说为啥,先看代码

namespace ExtensionMethod

{

    public interface ICount

    {

        int Add(int x, int y);

    }

 

    public static class ExtensionInterface

    {

        public static int Subtract(this ICount count, int x, int y)

        {

            return x - y;

        }

    }

 

}

 

看出问题了吗?啥?没有。哈哈,我第一次也没有看出来。大家想想,接口的一个特性是啥?就是接口并不自己实现方法,必须由实现该接口的类来实现方法,对不啦?但是,此时,对接口的扩展方法,已经实现了Subtract方法。这就对接口的本质造成了破坏。可能有人会问,那不能写成这样?

public static int Subtract(this ICount count, int x, int y)

 

呵呵,have a try,看看会出现啥?(读者作业)。

怎么用呢?

namespace ExtensionMethod

{

    class Program

    {

        static void Main(string[] args)

        {

            ICount count = new MyCount();

 

            count.Subtract(5, 4);

        }

    }

 

    class MyCount : ICount

    {

        public int Add(int x, int y)

        {

            return x + y;

        }

    }

 

}

 

这回看明白了,由于只是对接口的一个方法的扩展,且已经有了实现,所以,对实现接口的类就不会强迫其实现”Substract”方法。 但是,在使用接口的时候,Substract 却切切实实的在哪呢。

小贴士:

         个人还是建议少用对接口的扩展方法,因为这毕竟破坏了面向对象的本质,也不可能对实现接口的类进行行为上的限制。

约束

1) 扩展方法必须放在static 类里面,且本身也是static的。

2) 扩展方法的第一参数必须是你要扩展的类型,this + 类型 + 参数名。

3) 每一个扩展方法之可以被内存中正确的实例调用,或者通过其所处的静态类调用。

4) 扩展方法不可以直接访问扩展类型的成员。

比如

    public class Car

    {

        public int Speed { get; set; }

 

        public void SpeedUp() { Speed++; }

    }

 

    public static class CarExtension

    {

        public static void SpeedDown(this Car car)

        {

            // It's wrong

            // Speed--;

 

            // It's right

            car.Speed--;

        }

    }

 

扩展方法的本质

先看如下代码

    class Program

    {

        static void Main(string[] args)

        {

            ICount count = new MyCount();

 

            // They are same

            count.Subtract(5, 4);

          

            ExtensionInterface.Subtract(count, 5, 4);

        }

    }

 

哈哈,被骗了吧,其实是微软玩的一个障眼法。其实它就是 ExtensionInterface.Subtract(count, 5, 4);”。

 

个人建议

呼,总算写完了,个人一点点建议哈

1) 扩展方法的命名要遵循所扩展类型的其他方法的命名习惯。

2) 相关类型的扩展方法放到相关类型的命名空间下,在加一个Extension。比如关于System.Data的扩展方法的命名空间就是System.Data.Extension

 

 

 

posted @ 2009-09-23 14:07 麦穗 阅读(116) 评论(0) 编辑
摘要: 存在必有存在的理由。这是大自然给的一个真理。在IT圈,也是这样。.net, java, 开源,不开源,各种令人眼花缭乱的语言,都有自己存在的理由,有自己的优势和不足。Anyway,它存在,我们就要接受它。任何破坏这个平衡,抹杀一个事物存在的行为都是无用且应该令人唾弃的。 我喜欢.net,我就喜欢它的简约而不简单。容易上手,但是却蕴含很多深刻的道理。之前,我也属于拖拽派的,但是慢慢,我发现我不懂得真...阅读全文
posted @ 2009-09-21 13:09 麦穗 阅读(47) 评论(0) 编辑
摘要: 不想做外包了。这样一个项目一个项目换,一点职业规划都没有。将来最多是个技术能手。 应该去做行业解决方案,成为一个行业的专家。阅读全文
posted @ 2008-07-18 21:14 麦穗 阅读(31) 评论(1) 编辑
摘要: 终于飞来了。既然来了,就不走了阅读全文
posted @ 2008-07-10 15:30 麦穗 阅读(17) 评论(0) 编辑