再谈static在C++和C#中的不同处理

先看这段C#代码

    public class C 
        
public static void M() 
            Console.WriteLine(
"call in class C"); 
        }
 
    }

    
    
public class D : C 
        
public new static void M() 
            Console.WriteLine(
"call in class D"); 
        }
 
    }

    
    
public class E<T> where T : C 
        
public static void N() 
            T.M(); 
        }
 
    }

代码是错误的,不允许一个instance来call一个static method。如果你编译的话,会提示:
Error 2 'T' is a 'type parameter', which is not valid in the given context

为什么?
从语言设计的角度来看,针对上面的代码,下面的三种情况只能有一种为true。
1. 本身就是错误的写法
2. E.N() calls C.M() no matter what T is.
3. E.N() calls C.M() but E.N() calls D.M().

如果按照2设计,会有用户期望当T是class D的时候,执行class D的method M,而不是C。Static之所以是static,因为它在编译时刻就可以被确切的determined,或者说,在静态代码分析阶段,这个方法就可以被确定了。所以,如果按照3的方式来设计,我们就违背了这个原则。
这样,只有1了。

另外的解释:
1. virtual static,为什么没这个东西?
2. 没有this指针而已
(以上内容转自同事的一个blog,做了简单的修改)

不过,不清楚C++里面为什么允许这么做?
public class Test{
    
public static void Say(){}
}


Test t;
Test
* t2 = new Test();

t.Say();
t2
->Say();

posted on 2007-10-29 16:34 鞠强 阅读(1650) 评论(8)  编辑 收藏 所属分类: .NET CLR研究

评论

#1楼  2007-10-29 16:52 neoragex2002      

前面的问题:
没有this才是正解吧。virtual this,连this都没有,怎么去找虚表?一错。OK,你可以说,虚表不就是一个类一张嘛,照样找得到,可静态绑定虚表其实是违背了多态精神的,与其如此还不如直接调用好,而virtual就是为了运行时绑定,so 这是二错。因此,virtual this的语义横竖是解释不同的。

后面的问题:
为了追求灵活性吧,比方说有模板的情况下,用##宏替换写类名比较ugly,不太符合强类型的风格,所以还是通过对象名引用比较称手。C#里面去掉了很多C++语法、语义的歧义,所以更robust,不太容易被钻孔子玩文字游戏。   回复  引用  查看    

#2楼 [楼主] 2007-10-29 17:12 鞠强      

1楼的老大,有空你写一个这个主题的帖子吧!
强烈要求,:D   回复  引用  查看    

#3楼  2007-10-29 17:18 neoragex2002      

这个...随便说说,上不了台面的理解了,一般教材里面都有的:)   回复  引用  查看    

#4楼  2007-10-29 17:59 rex xiang      

依稀记得从某篇文章中得知, 这是个语法问题:

C#中只能用type.StaticMethod()方式访问某类型的静态成员, instance.StaticMethod()的调用方式是无效的.
java中则没有这个限制.   回复  引用  查看    

#5楼  2007-10-29 18:05 rex xiang      

C# 语言规范  

10.5.2 静态和实例方法

若一个方法声明中含有 static 修饰符,则称该方法为静态方法。若其中没有 static 修饰符时,则称该方法为实例方法。

静态方法不对特定实例进行操作,在静态方法中引用 this 是编译时错误。

实例方法对类的某个给定的实例进行操作,而且可以用 this(第 7.5.7 节)来访问该实例。

E.M 形式的成员访问(第 7.5.4 节)中引用一个方法时,如果 M 是静态方法,则 E 必须表示含有 M 的一个类型,而如果 M 是实例方法,则 E 必须表示含有 M 的类型的一个实例。

(第 10.2.5 节)对静态成员和实例成员之间的差异进行了进一步讨论。

ref:
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/csspec/html/vclrfcsharpspec_10_5_2.asp

  回复  引用  查看    

#6楼  2007-10-29 18:14 装配脑袋      

其实VB.NET支持那样调用的说。。所以只是设计偏好问题。   回复  引用  查看    

#7楼  2007-10-29 18:31 地狱门神      

VB.Net里面会出现警告来着。   回复  引用  查看    

#8楼 [楼主] 2007-10-29 18:45 鞠强      

看来是老大们自己的偏好,没啥太多的理由。   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接:
 


<2007年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

公告

web counter
访问量是此计数器+213636(粗略值) 大家不要给我私人留言了,经常忘记看。有事情往这里发邮件吧:juqiang@live.com,多谢!!!

与我联系

搜索

 

常用链接

留言簿(97)

我参加的小组

我参与的团队

我的标签

随笔分类

随笔档案

相册

积分与排名

最新评论

阅读排行榜

评论排行榜