.NET,你忘记了么?(八)—— 从dynamic到特性误用 [转]
1. 摘要
每个程序员都想写出漂亮的代码,但是什么是漂亮,这个我想每个人都有着自己的看法。那么我就说几种典型的想法:
A. 写出别人看不懂的代码,让别人觉得很高深。
B. 写出简短的代码
C. 用最新的语言特性写出代码
这个我不发表评论,毕竟每个人有着自己的观点,我也不能证明自己的就是对的。但是在这里,我想说一些典型的误用。
2. 从dynamic谈起
作为C#4.0的更新之一,dynamic已经越来越被推到了很多技术论坛的第一线。我看了很多关于dynamic的讲解,但是我还是我一贯的观点。既然我们用的微软的东西,那么我们在使用一个语言特性的同时,我们首先要弄清微软为什么要推出这门语言,不要盲目去使用。这样往往会适得其反。
那下面我就看大多数教程中的一个传统代码:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
dynamic p = new People("Test");
Console.WriteLine(p.GetName());
}
}
class People
{
private string name;
public string GetName()
{
return name;
}
public People(string name)
{
this.name = name;
}
}
}但是正如很多评论中的质疑的一样,这样的操作究竟有什么作用?(我并不是怀疑很多作者不懂这个,而是说这个会误导很多人)于是很多人就会不明不白地去跟风,去乱用dynamic。
那么我们就在这里说清,究竟为何dynamic。
3. dynamic和var
在说这两个关键字之前,我们要先搞清楚两个概念。什么叫强类型语言,什么叫弱类型语言。
一句经典的话我想最能解释他们的区别了:static typing when possible,dynamic typing when needed.
其实也就是说:静态语言是在编译时确定类型,而弱类型是在运行时确定类型。
一个简单的例子就能看出他们的区别:
首先是使用var的情况:
接下来是dynamic:
4. 究竟为何dynamic
在国外某博客中,我记得有这样一个说法,是说dynamic会颠覆传统的C#编程方式,从前说世间万物皆为对象,那么现在世间对象皆为dynamic。
class People
{
private dynamic name;
public People(dynamic name)
{
this.name = name;
}
public dynamic Introduce()
{
dynamic s = "Hello,I am" + name;
return s;
}
public delegate dynamic Notify(dynamic argument);
}不过,就我个人而言,并不认同这种说法,已经有很多《“深入剖析”dynamic》之类的文章了,我就不在多写了。总之dynamic会对效率产生很大的影响。如果这样滥用dynamic:
A. 对程序的效率有很大影响
B. Visual Studio 强大的智能感知功能被完全废弃了。
既然这样,那么我们为什么要使用dynamic,就我的理解而言:
A. 语言的互操作,比如去调用C++的一个Com组件,我们完全可以用dynamic取代反射略显复杂的语法。
B. 我们都知道var只能用于变量,而无法用于属性,而我们使用var的情况往往是因为我们不大容易确定某一个变量(或者属性)的类型,同样,很可能出现一个类的属性或者方法返回类型不易确定返回类型的情况,这个时候,我们就可以用dynamic了。比如:
public dynamic GetAllGrilFriendsDetails()
{
var gfDetails = from o in db.People
where o.name = this.name
select new
{
Name = o.firstName + o.lastName,
Age = o.age,
Address = o.address
};
return gfDetails;
}为什么我在方法内部去用 dynamic gfDetails,如果你讨厌去看IL代码细节,那么我们只看由于dynamic产生的反编译C#代码数量也许就能吓到你了:
5. 从误用继续说开去
任何一种事物永远都是双面性的,同样,任何一种新鲜事物的产生总是会有着他的利和他的弊。究竟是利还是弊,其本质原因不在于他本身,而在于他周围的环境对他的使用是利大于弊,还是利小于弊。
任何一个C#新语言特性也是亦然。而他周围的环境就是我们程序员。
我看到过太多太多的误用,比如对泛型的误用,对委托的误用,对扩展方法的误用。
在这里就再谈谈扩展方法的误用。
6. 何时扩展方法
我在<Javascript玩转Prototype(二) >中提过Prototype的缺点,在这里我只说一点:能够动态地添加属性和方法固然是增加了灵活性。可是我们讨论一种情况,100个人同时来开发一个Javascript的项目,很多没经验的人爱上了玩转prototype,一个人往这个类里加一个方法,还面向对象么?
扩展方法也是一样,100个开发者同时去开发一个项目,每个人都写一个扩展方法,那么这个项目会乱成什么样大家可想而知。
那么什么时候该用扩展方法,我个人认为只有三种情况:
A. 你独立负责一个组件的编写,而这个组件需要调用其他组件中的类,而你常常需要用到某个类中的某个他并为提供的“方法”。那么这个时候,你可以在你的组件内特殊放置一个类,用来容纳你所需的扩展方法。
B. 一个团队面对的一个已经封装好的组件,但是某个方法是这个组件没有提供的,重写组件实在麻烦,那好吧。扩展方法。
C. 其实这个与第二点有些相似,当你面对的是.NET Framework中提供的类库,那么没办法,只能扩展方法。
#2楼 2009-05-29 14:46 Gray Zhang
#3楼 2009-05-29 15:14 winter-cn未登陆[未注册用户]
----------------------------------------------------------
你的这个理解也是有些问题的 var其实本质是懒得写类型 让编译系统自动帮你决定 所以问题不是出在属性或者局部变量上
dynamic把对类型的检测延迟到运行时 dynamic最主要的意义还是改进封装性 使得你能够编写更加灵活通用代码 同时运行时检测类型并捕获异常 可以真正做到duck type
其实可以想到 dynamic有很多有趣的用法 比如跟匿名委托配合
#4楼 2009-05-29 15:16 winter-cn未登陆[未注册用户]
Gray Zhang: 请问泛型有效率影响的证据?从我的理解上,泛型是生成新的类型,拿来的效率影响之说呢
--------------------------------------------------------
.net的泛型会略微影响效率 跟C++略有些不同
#5楼 2009-05-29 15:26 Jeffrey Zhao
#6楼 2009-05-29 15:41 Gray Zhang
#7楼 2009-05-29 15:41 Gray Zhang
#8楼 2009-05-29 16:05 Jeffrey Zhao
#10楼 2009-05-29 16:51 Jeffrey Zhao
结论:范型不会影响性能。
http://pic.cnitblog.com/face/u9419.png
#14楼 2009-05-29 17:47 Jeffrey Zhao
泛型应该是减少代码的。
要实现同等功能,ClassA<Type> where Type : IInterfaceA 大致等同于
ClassA
{
public IInterfaceA A {get;set;}
}
用泛型写要少写很多代码。
如果是 Class<TType1<TType2<TType3<TType4>>>> 这样的泛型,节省的代码就更多了。
编译后的代码大小,老赵上面也说了。
C#下泛型烦在写的时候太麻烦。
像写个Class<TType1<TType2<TType3<TType4<TType5<TType6<TType7<TType8<TType9>>>>>>>>> 这样的泛型类,光写 where 能把人折腾死。
http://pic.cnitblog.com/face/u6006.jpg
泛型确实会导致一定的代码膨胀,编译器有时候需要为不同的特定类型,生成不同的代码
.NET,你忘记了么?(八)—— 从dynamic到特性误用 [转]的更多相关文章
- 设计模式(八)Dynamic Proxy Parttern 动态代理模式
举例: jdk自带动态代理 javaassit字节码操作库实现 CGLIB ASM底层操作 实际例子: 使用jdk自带动态代理 java.lang.reflect.Proxy 作用 动态生成代理类和对 ...
- C# 新特性 dynamic的使用及扩展
个人而言感觉C#的dynamic是一个特别实用的东西,为日常开发工作中的封装,数据传递等带来了很高的可扩展性. C#4.0中通过对数据类型后期绑定的支持,演化出了dynamic.任何直接声明为这种类型 ...
- Spark中的Phoenix Dynamic Columns
代码及使用示例:https://github.com/wlu-mstr/spark-phoenix-dynamic phoenix dynamic columns HBase的数据模型是动态的,很多系 ...
- dynamic
dynamic的特性很多,好像和反射也有关,不过这里先介绍一个特性,关于反射的再补充. 我们来看一个方法: public virtual ActionResult Insert(T info) 有一个 ...
- 利用dynamic简化数据库的访问
今天写了一个数据库的帮助类,代码如下. public static class DbEx { public static dynamic ReadToObject(this IDataReader r ...
- Linux 内核引导选项简介
Linux 内核引导选项简介 作者:金步国 连接地址:http://www.jinbuguo.com/kernel/boot_parameters.html 参考参数:https://www.cnbl ...
- 进阶系列(10)—— C#元数据和动态编程
一.元数据的介绍 元数据是用来描述数据的数据(Data that describes other data).单单这样说,不太好理解,我来举个例子.下面是契诃夫的小说<套中人>中的一段,描 ...
- 值得尝试的十款 GNOME Shell 扩展
值得尝试的十款 GNOME Shell 扩展 作者: JACK WALLEN 译者: 核子可乐 | 2016-09-22 17:10 评论: 6 收藏: 1 当 GNOME Shell(即 GNO ...
- null==a和a==null的区别
在项目代码中在if判断中会经常看到一些老司机这样写:if(null == a),而我由于习惯会写成if(a == null),这两种有什么区别呢? 其实两种并没有什么区别,只是前者在细节处理上.我们在 ...
随机推荐
- DataTable AsEnumerable 的使用
var p = DataTable.AsEnumerable().Where(t => t.Field<int>("ChannelID") == int.Pars ...
- js设计模式
http://www.csdn.net/article/2011-09-02/303983 阐明JavaScript设计模式.CSDN研发频道对此文进行了整理选取部分内容,供开发者学习.参考. 内容如 ...
- INNO SETUP 获得命令行参数
原文 http://www.cnblogs.com/ahuo/archive/2009/07/30/1534998.html ); Result := CmdLine; ...
- 在C#中调用Win32函数EnumWindows枚举所有窗口。
原文 http://www.cnblogs.com/mfm11111/archive/2009/06/30/1514322.html 开发旺旺群发软件,难点及重要技术点分析(一) 一. ...
- 从Linux终端管理进程:10个你必须知道的命令
从Linux终端管理进程:10个你必须知道的命令 Linux终端有一系列有用的命令.它们可以显示正在运行的进程.杀死进程和改变进程的优先级.本文列举了一些经典传统的命令和一些有用新颖的命令.本文提到的 ...
- java 解析 xml (DOM方法全)
Java 处理 XML 的三种主流技术及介绍 http://www.ibm.com/developerworks/cn/xml/dm-1208gub/ 这篇文章讲的比较详细,下面我主要介绍 dom方法 ...
- Makefile里面的$(MAKE)到底是啥
[已解决]Makefile里面的$(MAKE)到底是啥 [复制链接] http://bbs.chinaunix.net/thread-4164499-1-1.html make 定义了很多默认变量,像 ...
- C#委托 Lamda表达式
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- sqlserver 2008存储过程 多个可空条件任意组合
很多程序员在实际开发中,经常遇到这种情况,列表上方有很多条件,包含下拉框,输入框等等,这些条件都可以不输入,如果我们需要写一个存储过程,很多条件挨个判断是否为空,且进行任意组合,任何一个开发人员都会疯 ...
- OC——封装(初级与高级)
所谓的封装,就是通过定义方法或者函数去操作成员属性或者成员变量,而不是直接通过指针方式去操作.借此达到提高代码安全性,代码可行性以及代码执行效率的目的. 1:初级封装,对成员变量进行封装. #impo ...