日期:2014-05-18 浏览次数:21225 次
struct以及以下的基本数据类型,赋值或者函数参数都传递的值(拷贝),除非使用ref关键字(函数参数)。
?
object的赋值或者函数参数都传递的引用,但是函数参数的时候,传递后的引用相当于一个常引用(不能=new xxx()之类了),如果使用ref关键字,?则这个引用可以自由修改。
也就是说,C#里object和struct以下的基本数据类型传递起来并没有太大不同,只是object变量本身的值就是指的引用(实际对象的地址)。
?
另外,怀念Delphi的with关键字,于是网上找到一个C#的实现:
首先定义这个extention method
?
public static void Use<T>(this T item, Action<T> work) { work(item); }
?其次可以这样使用了:
?
this.StatusProgressBar.Use(p => { p.IsIndeterminate = false; p.Visibility = Visibility.Visible; p.Minimum = 0; p.Maximum = 100; p.Value = percentage; });
?
既然说到Action:
System.Func系列是带返回值类型的预定义delegator;而System.Action系列都是不带返回值类型的预定义delegator。
?
关于delegater(lambda表达式)?的capture,例如
?
void OneMethod() { var local_var = SomeFactory.NewObj(); if (_handler == null) { _handler = (s, e) => {CallSomeOtherMethod(local_var);}; } UI.control1.OnSomeChange += _handler; }
如果UI一直在“清空control1;new新的control1之后走OneMethod()挂载响应”这个循环,但是SomeFactory.NewObj()产生的local_var每次都不一样,那么每次挂载的哪个匿名lamba里面的local_var其实总是第一次的那个local_var,而非看似应该是的每次都在改变的local_var。
说白了就是,局部变量capture到lambda里面,都是相当于capture了一个值,如果一直用这个lambda,不管局部变量变成什么,这个lambda用的一直是创建这个lambda时该局部变量的取值。
?
?
关于extension method。用它可以在一定程度上满足对于类似于ruby的mixin module的需求。
例如,我的project中的每个类都需要加载资源字符串的方法。
当然使用StaticStringClass.StaticGetString(key)的方式,但是这样写起来——字符太多了。于是想让每个类中都有一个S(key)的方法可以用。继承不可行,C#单继承,这种功能上属于util的方法不适合当父类,何况也不应该让所有类有相同的父类。于是想通过mixin的方式来创造一个S(key)添加到类里面。
于是就用extension method这样解决:
?
public interface ExtensionsInterfaceToHandleStringResource { } public static class ExtensionsInterfaceToHandleStringResourceImplementaion { public static String S(this ExtensionsInterfaceToHandleStringResource @this, string key) { // 读取资源字符串 return ret; } }
? 这样只要声明自己继承 ExtensionsInterfaceToHandleStringResource的类,就都有了S(key)这个extension method。不过要注意,使用S(key)的时候必须加this前缀,即this.S(key),这个没辙了,extension method都这德行(必须是obj.XXX才能使用)。
?
?
原来以为C#跟Java都是认为所有的方法都是virtual的(不根据指针/引用类型调用类定义所在内存的方法,而是根据实际对象的虚函数表寻找方法入口),今天一试,发现C#这方面还是C++之类“静态”语言的习惯,想要实现virtual方法,需要在基类的方法定义上声明virtual。嗯,虽然在关键字上更让人想起delphi,这蛮好的,继承类指明override让代码易读,调用和维护时不易出错。
?
觉得Java那样简化概念蛮好的,毕竟多态一般都是用接口(或父类)指针来调用实现类(或子类)的方法,而至少我都好像没怎么用到过“截断”式的调用。
?
回到C#,如果要用virtual式的(运行时绑定,动态绑定,对象所在内存的虚函数表,常见的Java式接口式多态),在父类方法使用virtual关键字,子类方法使用override关键字;如果要用“截断”式的(编译时绑定,静态绑定,即便是子类对象用父类指针调用也只能调用到父类的方法,方法入口在类的定义所在的内存而非对象所在内存的虚函数表),则父类使用普通方法就行,子类加一个new关键字,表达一个overwrite的意思,在delphi那里,相同情况下用的关键字是reintroduce。