I noticed that with the optional parameters in C# 4 if you specify a parameter as optional on an interface you DON'T have to make that parameter optional on any implementing class:
我注意到,对于c# 4中的可选参数,如果您在接口上指定一个可选参数,则不必在任何实现类上使该参数可选:
public interface MyInterface
{
void TestMethod(bool flag = false);
}
public class MyClass : MyInterface
{
public void TestMethod(bool flag)
{
Console.WriteLine(flag);
}
}
and therefore:
因此:
var obj = new MyClass();
obj.TestMethod(); // compiler error
var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false
Does anyone know why optional parameters are designed to work this way?
有人知道为什么可选参数被设计成这样吗?
On one hand I suppose the ability to override any default values specified on the interfaces is useful though to be honest I'm not sure if you should even be able to specify default values on the interface as that should be an implementation decision.
一方面,我认为重写接口上指定的任何默认值的能力是有用的,但是说实话,我不确定您是否应该能够在接口上指定默认值,因为这应该是实现决策。
On the other hand, this disconnect means you can't always use the concrete class and the interface interchangeably. This of course, wouldn't be a problem if the default value is specified on the implementation, but then if you're exposing your concrete class as the interface (using some IOC framework to inject the concrete class for instance) then really there's no point having the default value as the caller will have to always provide it anyway.
另一方面,这种断开意味着您不能总是交替地使用具体类和接口。当然,这不会是一个问题如果指定默认值的实现,但是如果你暴露你的具体类的接口(使用IOC框架注入一些具体类的实例)然后真的没有点有默认值总是调用者必须提供。
4 个解决方案
#1
196
UPDATE: This question was the subject of my blog on May 12th 2011. Thanks for the great question!
更新:这个问题是我2011年5月12日博客的主题。谢谢你的问题!
Suppose you have an interface as you describe, and a hundred classes that implement it. Then you decide to make one of the parameters of one of the interface's methods optional. Are you suggesting that the right thing to do is for the compiler to force the developer to find every implementation of that interface method, and make the parameter optional as well?
假设您有一个如您所描述的接口,以及100个实现它的类。然后,您决定让接口方法中的一个参数成为可选的。您是否认为正确的做法是让编译器强制开发人员找到接口方法的每个实现,并使参数也是可选的?
Suppose we did that. Now suppose the developer did not have the source code for the implementation:
假设我们这样做。现在假设开发人员没有实现的源代码:
// in metadata:
public class B
{
public void TestMethod(bool b) {}
}
// 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
How is the author of D supposed to make this work? Are they required in your world to call up the author of B on the phone and ask them to please ship them a new version of B that makes the method have an optional parameter?
《D》的作者是如何让这个作品成功的?在你的世界里,是否需要他们打电话给B的作者,请他们将B的新版本发给他们,使该方法具有可选参数?
That's not going to fly. What if two people call up the author of B, and one of them wants the default to be true and one of them wants it to be false? What if the author of B simply refuses to play along?
它不会飞。如果两个人打电话给B的作者,其中一个想让默认值为真,另一个想让它为假呢?如果B的作者拒绝合作怎么办?
Perhaps in that case they would be required to say:
也许在这种情况下,他们会被要求说:
class D : B, MyInterface
{
public new void TestMethod(bool b = false)
{
base.TestMethod(b);
}
}
The proposed feature seems to add a lot of inconvenience for the programmer with no corresponding increase in representative power. What's the compelling benefit of this feature which justifies the increased cost to the user?
所提出的特性似乎给程序员增加了许多不便,并且没有相应增加代表性的功能。这个特性的引人注目的好处是什么?
#2
45
An optional parameter is just tagged with an attribute. This attribute tells the compiler to insert the default value for that parameter at the call-site.
一个可选参数仅仅被标记为一个属性。此属性告诉编译器在调用站点上插入该参数的默认值。
The call obj2.TestMethod();
is replaced by obj2.TestMethod(false);
when the C# code gets compiled to IL, and not at JIT-time.
obj2.TestMethod()的调用;被obj2.TestMethod(假);当c#代码编译到IL时,而不是在抖动时。
So in a way it's always the caller providing the default value with optional parameters. This also has consequences on binary versioning: If you change the default value but don't recompile the calling code it will continue to use the old default value.
所以在某种程度上,总是调用者提供具有可选参数的默认值。这也会对二进制版本控制产生影响:如果您更改了默认值,但不重新编译调用代码,它将继续使用旧的默认值。
On the other hand, this disconnect means you can't always use the concrete class and the interface interchangeably.
另一方面,这种断开意味着您不能始终使用具体的类和接口。
You already can't do that if the interface method was implemented explicitly.
如果接口方法被显式地实现,您已经不能这样做了。
#3
24
Because default parameters are resolved at compile time, not runtime. So the default values does not belong to the object being called, but to the reference type that it is being called through.
因为默认参数在编译时解析,而不是在运行时解析。因此,默认值不属于被调用的对象,而是属于被调用的引用类型。
#4
5
Optional parameters are kind of like a macro substitution from what I understand. They are not really optional from the method's point of view. An artifact of that is the behavior you see where you get different results if you cast to an interface.
可选参数有点像我理解的宏替换。从方法的角度来看,它们并不是可选的。如果您将结果转换到一个接口,那么您将看到这种行为。
#1
196
UPDATE: This question was the subject of my blog on May 12th 2011. Thanks for the great question!
更新:这个问题是我2011年5月12日博客的主题。谢谢你的问题!
Suppose you have an interface as you describe, and a hundred classes that implement it. Then you decide to make one of the parameters of one of the interface's methods optional. Are you suggesting that the right thing to do is for the compiler to force the developer to find every implementation of that interface method, and make the parameter optional as well?
假设您有一个如您所描述的接口,以及100个实现它的类。然后,您决定让接口方法中的一个参数成为可选的。您是否认为正确的做法是让编译器强制开发人员找到接口方法的每个实现,并使参数也是可选的?
Suppose we did that. Now suppose the developer did not have the source code for the implementation:
假设我们这样做。现在假设开发人员没有实现的源代码:
// in metadata:
public class B
{
public void TestMethod(bool b) {}
}
// 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
How is the author of D supposed to make this work? Are they required in your world to call up the author of B on the phone and ask them to please ship them a new version of B that makes the method have an optional parameter?
《D》的作者是如何让这个作品成功的?在你的世界里,是否需要他们打电话给B的作者,请他们将B的新版本发给他们,使该方法具有可选参数?
That's not going to fly. What if two people call up the author of B, and one of them wants the default to be true and one of them wants it to be false? What if the author of B simply refuses to play along?
它不会飞。如果两个人打电话给B的作者,其中一个想让默认值为真,另一个想让它为假呢?如果B的作者拒绝合作怎么办?
Perhaps in that case they would be required to say:
也许在这种情况下,他们会被要求说:
class D : B, MyInterface
{
public new void TestMethod(bool b = false)
{
base.TestMethod(b);
}
}
The proposed feature seems to add a lot of inconvenience for the programmer with no corresponding increase in representative power. What's the compelling benefit of this feature which justifies the increased cost to the user?
所提出的特性似乎给程序员增加了许多不便,并且没有相应增加代表性的功能。这个特性的引人注目的好处是什么?
#2
45
An optional parameter is just tagged with an attribute. This attribute tells the compiler to insert the default value for that parameter at the call-site.
一个可选参数仅仅被标记为一个属性。此属性告诉编译器在调用站点上插入该参数的默认值。
The call obj2.TestMethod();
is replaced by obj2.TestMethod(false);
when the C# code gets compiled to IL, and not at JIT-time.
obj2.TestMethod()的调用;被obj2.TestMethod(假);当c#代码编译到IL时,而不是在抖动时。
So in a way it's always the caller providing the default value with optional parameters. This also has consequences on binary versioning: If you change the default value but don't recompile the calling code it will continue to use the old default value.
所以在某种程度上,总是调用者提供具有可选参数的默认值。这也会对二进制版本控制产生影响:如果您更改了默认值,但不重新编译调用代码,它将继续使用旧的默认值。
On the other hand, this disconnect means you can't always use the concrete class and the interface interchangeably.
另一方面,这种断开意味着您不能始终使用具体的类和接口。
You already can't do that if the interface method was implemented explicitly.
如果接口方法被显式地实现,您已经不能这样做了。
#3
24
Because default parameters are resolved at compile time, not runtime. So the default values does not belong to the object being called, but to the reference type that it is being called through.
因为默认参数在编译时解析,而不是在运行时解析。因此,默认值不属于被调用的对象,而是属于被调用的引用类型。
#4
5
Optional parameters are kind of like a macro substitution from what I understand. They are not really optional from the method's point of view. An artifact of that is the behavior you see where you get different results if you cast to an interface.
可选参数有点像我理解的宏替换。从方法的角度来看,它们并不是可选的。如果您将结果转换到一个接口,那么您将看到这种行为。