首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么在接口上定义的C# 4可选参数在实现类时不强制执行?

为什么在接口上定义的C# 4可选参数在实现类时不强制执行?
EN

Stack Overflow用户
提问于 2011-02-07 22:59:10
回答 7查看 116.8K关注 0票数 395

我注意到,在C# 4中使用可选参数时,如果您在接口上指定了一个可选参数,则t必须使该参数在任何实现类上都是可选的:

代码语言:javascript
复制
public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

因此:

代码语言:javascript
复制
var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

有人知道为什么可选参数被设计成这样工作吗?

一方面,我认为覆盖接口上指定的任何默认值的能力是有用的,尽管老实说,我甚至不确定您是否应该能够在接口上指定默认值,因为这应该是一个实现决策。

另一方面,这种断开意味着您不能总是互换地使用具体的类和接口。当然,如果在实现上指定了默认值,这将不是问题,但是如果您将具体的类公开为接口(例如,使用某个IOC框架注入具体的类),那么使用默认值是没有意义的,因为调用者无论如何都必须始终提供它。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-02-08 00:23:24

更新:This question was the subject of my blog on May 12th 2011. Thanks for the great question!

假设您有一个如您所描述的接口,以及一百个实现它的类。然后,您决定将该接口的一个方法的一个参数设为可选。您是否建议编译器应该强制开发人员找到该接口方法的每个实现,并将参数设为可选?

假设我们这样做了。现在假设开发人员没有实现的源代码:

代码语言:javascript
复制
// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

代码语言:javascript
复制
// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

D的作者应该如何做到这一点?在你的世界里,他们是否需要打电话给B的作者,让他们给他们发一个新版本的B,让这个方法有一个可选的参数?

那是不会飞起来的。如果两个人打电话给B的作者,其中一个人希望缺省值为true,而另一个人希望默认值为false,该怎么办?如果B的作者只是简单地拒绝一起玩呢?

也许在这种情况下,他们会被要求说:

代码语言:javascript
复制
class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

拟议的功能似乎为程序员增加了许多不便,但没有相应地增加代表性能力。此功能的显著优势是什么,可以证明用户增加的成本是合理的?

更新:在下面的评论中,supercat建议了一种语言功能,它将真正地增加语言的功能,并支持一些类似于这个问题中描述的场景。仅供参考,该功能--接口中方法的默认实现--将被添加到C# 8中。

票数 262
EN

Stack Overflow用户

发布于 2011-02-07 23:14:59

一个可选参数只是用一个属性做了标记。这个属性告诉编译器在调用点插入该参数的默认值。

在将obj2.TestMethod();代码编译为IL时,而不是在即时编译时,C#调用将被obj2.TestMethod(false);替换。

因此,在某种程度上,总是由调用者提供带有可选参数的默认值。这也会对二进制版本控制产生影响:如果您更改了默认值,但没有重新编译调用代码,它将继续使用旧的默认值。

另一方面,这种断开意味着您不能总是互换地使用具体的类和接口。

如果接口方法是implemented explicitly,就不能这样做。

票数 50
EN

Stack Overflow用户

发布于 2011-02-07 23:12:48

因为默认参数在编译时解析,而不是在运行时解析。因此,默认值不属于被调用的对象,而是属于被调用的引用类型。

票数 30
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4922714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档