C# .net 4.0新特性的可选参数和命名参数,使用的话会给函数的重载造成困扰啊。
比如voidd(inta=1,intb=1,intc=1)voidd(inta=1,intb=1)用这个新特性调用d(a:1,b:2)是调用哪个呢...
比如void d(int a=1,int b=1,int c=1) void d(int a=1,int b=1)用这个新特性调用d(a:1,b:2) 是调用哪个呢
展开
4个回答
展开全部
这个问题是很有意思的一个问题,楼上两个兄弟说的都不错,但都不有讲原理。只说是优先匹配,其实他们的这个优先匹配是不存在的,事实是DLR与CLR之间的优先级问题。
也就是说,如果存在DLR的情况下,是优先执行DLR的,而且这个不是优先级,而是DLR在CLR的上层,所以必须先执行DLR。
而这里边的可选参数和具体的DLR关系还是很大,倒是合名参数是在DLR之间的。以可选参数为例:
void d(int a = 1,int b=1),如果只有这个函数,没有进行重载的情况下,调用d()是可以成功的,这个原因就在于DLR,DLR的作用就是它指导你的d()演变了d(1,2)[d(a:1,b:2)]的然后再去调用,也就是说,当我们支持命名参数,支持可选参数时,这个方法一定在DLR中的有注册,它可清楚地知道你要调用哪个方法。而你在重构时,那就是表再见在DLR中注册的顺序了。
例如在你的疑问中,d(a:1,b:2)要调用哪个?DLR会为你优先匹配到参数最匹配的方法。而这里自然会调用参数相同的。
所以楼上两位说的还并错的,但是这里要注意的是,你举的例子也是一个特殊的情况,与编程思想有偏离的。事实上我们并不经常这样用的。因为中间多一重DLR的执行,而且这个执行是一个动态的执行——性能上上海所下降的,所以在不得已的情况下,我们并不这样使用。
先说一下可选参数的使用范畴。当就对void d(int a=1,int b=2)的定义来说,它事实上可以使用void d(){a=1;b=2;}这类似的重载实现在的。但是由于过多个有默认值得的情况下,显然是增加了我们的代码量,而且我们需要这多种不同的调用方式,那么这种情况下可以使用。可见,它对于我们的面向对象编程没有任何影响,它只是减轻我们编码,从而节省开发周期而已。并不是必须要用的,或是推荐要用的。
再说一下命名参娄,比如存在这样的一个定义:void d(int a=1,string b=null,.............,string dd='')事实上我们在调用时只需要传入一个参数,其他的我们都采用默认值的情况下,如果不支持命名参数,那么我必须这样调用:
d(1,null,........'ddd');这要在书写代码时我们对于这样的函数是在浪费时间的。如果使用重载的情情况,又回到了相应的代码量的问题上。早期的方式是:
void d(){//全调部用默认值;}
void d(int a){ //更改a参数后,再调用d};
。。。。。。
或者把顺序倒过来:
void d(int a ,string b,.......string dd){};
void d(int a){d{a,默认值,默认值,........);}
。。。。。。
显然代码量太大,而可选参数能提供我们这种使用方式,则不用增加代码。
但是我们还是无法实列表中有相同类型参数的默认(以前版本中,要增加说明是那个参数的额外参数)。而如果命名参数,则直接写:
void d(dd:'ddd');即可。
事实上在office等办公接口的应用上最常见这种形式,所以有这种命名参数的出现。换名句来说,使用默认参数或命名参数,必须要考虑你的代码量与运行效率之间找一个平衡。并不是说一定要用,推荐替代原方式。
也就是说,如果存在DLR的情况下,是优先执行DLR的,而且这个不是优先级,而是DLR在CLR的上层,所以必须先执行DLR。
而这里边的可选参数和具体的DLR关系还是很大,倒是合名参数是在DLR之间的。以可选参数为例:
void d(int a = 1,int b=1),如果只有这个函数,没有进行重载的情况下,调用d()是可以成功的,这个原因就在于DLR,DLR的作用就是它指导你的d()演变了d(1,2)[d(a:1,b:2)]的然后再去调用,也就是说,当我们支持命名参数,支持可选参数时,这个方法一定在DLR中的有注册,它可清楚地知道你要调用哪个方法。而你在重构时,那就是表再见在DLR中注册的顺序了。
例如在你的疑问中,d(a:1,b:2)要调用哪个?DLR会为你优先匹配到参数最匹配的方法。而这里自然会调用参数相同的。
所以楼上两位说的还并错的,但是这里要注意的是,你举的例子也是一个特殊的情况,与编程思想有偏离的。事实上我们并不经常这样用的。因为中间多一重DLR的执行,而且这个执行是一个动态的执行——性能上上海所下降的,所以在不得已的情况下,我们并不这样使用。
先说一下可选参数的使用范畴。当就对void d(int a=1,int b=2)的定义来说,它事实上可以使用void d(){a=1;b=2;}这类似的重载实现在的。但是由于过多个有默认值得的情况下,显然是增加了我们的代码量,而且我们需要这多种不同的调用方式,那么这种情况下可以使用。可见,它对于我们的面向对象编程没有任何影响,它只是减轻我们编码,从而节省开发周期而已。并不是必须要用的,或是推荐要用的。
再说一下命名参娄,比如存在这样的一个定义:void d(int a=1,string b=null,.............,string dd='')事实上我们在调用时只需要传入一个参数,其他的我们都采用默认值的情况下,如果不支持命名参数,那么我必须这样调用:
d(1,null,........'ddd');这要在书写代码时我们对于这样的函数是在浪费时间的。如果使用重载的情情况,又回到了相应的代码量的问题上。早期的方式是:
void d(){//全调部用默认值;}
void d(int a){ //更改a参数后,再调用d};
。。。。。。
或者把顺序倒过来:
void d(int a ,string b,.......string dd){};
void d(int a){d{a,默认值,默认值,........);}
。。。。。。
显然代码量太大,而可选参数能提供我们这种使用方式,则不用增加代码。
但是我们还是无法实列表中有相同类型参数的默认(以前版本中,要增加说明是那个参数的额外参数)。而如果命名参数,则直接写:
void d(dd:'ddd');即可。
事实上在office等办公接口的应用上最常见这种形式,所以有这种命名参数的出现。换名句来说,使用默认参数或命名参数,必须要考虑你的代码量与运行效率之间找一个平衡。并不是说一定要用,推荐替代原方式。
展开全部
1楼的答案有问题的,按照程序的逻辑,d(a:1,b:2) 调用的是void d(int a=1,int b=1)是没有错的。不过如果试图用d(1) 这样调用,就会报出编译错误,错误描述是
The call is ambiguous between the following methods or properties:
意思就是无法区分调用的是哪个方法。但是如果是和方法声明相同个数的参数,则会调用对应的方法。
The call is ambiguous between the following methods or properties:
意思就是无法区分调用的是哪个方法。但是如果是和方法声明相同个数的参数,则会调用对应的方法。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
会造成困扰么?你传进几个参数就调用哪个重载函数,你上面那个传入了两个参数。所以d(a:1,b:2)调用的是void d(int a= 1,int b =1)
再怎么增加也不可能破坏以前的重载函数的定义的吧
再怎么增加也不可能破坏以前的重载函数的定义的吧
追问
新特性是你传2个参数他给函数两参数赋值,没传入的按照默认来
追答
上面那位兄弟说的不错。这里面有个优先级在里面。优先匹配参数相同的。绝对错不了。已测试
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
当你写了方法
void d(int a=1,int b=1,int c=1) 方法1
void d(int a=1,int b=1) 方法2
时d(a:1,b:2) 会调用方法2;
当只写了方法1时d(a:1,b:2) 会调用方法1;
void d(int a=1,int b=1,int c=1) 方法1
void d(int a=1,int b=1) 方法2
时d(a:1,b:2) 会调用方法2;
当只写了方法1时d(a:1,b:2) 会调用方法1;
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询