在不可变接口上公开可变接口的最佳方法是什么?
我想知道 C# 中关于可变/不可变接口的最佳实践是什么。
我喜欢只针对界面而不是真实的对象进行工作;删除依赖项并允许更轻松的测试。
我通常还公开只读接口,这可以减少错误。 然而,当我需要更改对象实例上的内容时,这会在实际代码中产生问题。
这就是我想要做的
public interface ISomething
{
string Name { get; }
}
public interface IMutableSomething : ISomething
{
string Name { get; set; }
}
...
public class ConsumerClass
{
//Note that I'm working against the interface, not the implementation
public void DoSomethingOnName(ISomething o)
{
var mutableO = (IMutableSomething) o;
mutableO.Name = "blah";
}
}
工作这种方式允许我轻松测试 ConsumerClass 并打破 ISomething 及其实现之间的任何依赖关系
我知道我可以将接口强制转换为实现,但这会引入对实际实现的依赖。
我可以做如下的事情,但我发现它丑陋且烦人,
public interface IMutableSomething : ISomething
{
void SetName(string newName)
}
or
public interface IMutableSomething // No inheritance, implementation impl. 2 interfaces
{
string Name { get; set; }
}
谢谢,
Eric G.
I wonder what's the best practice in C# regarding mutable / immutable interfaces.
I like to work against interfaces only instead of the real objects; remove dependencies and allow for easier testing.
I also usually expose interface that are read-only, which lower errors.
however this is creating a problem in the actual code when I need to change things on the instance of the object.
Here's what I'm trying to do
public interface ISomething
{
string Name { get; }
}
public interface IMutableSomething : ISomething
{
string Name { get; set; }
}
...
public class ConsumerClass
{
//Note that I'm working against the interface, not the implementation
public void DoSomethingOnName(ISomething o)
{
var mutableO = (IMutableSomething) o;
mutableO.Name = "blah";
}
}
Working this way allows me to easily test ConsumerClass and break any dependency between the ISomething and it's implementation
I know that I could cast the interface to the implementation but this would introduce a dependency on the real implementation.
I could do something like below but I find it ugly and annoying
public interface IMutableSomething : ISomething
{
void SetName(string newName)
}
or
public interface IMutableSomething // No inheritance, implementation impl. 2 interfaces
{
string Name { get; set; }
}
Thanks,
Eric G.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你的接口很好,但在你的消费者代码中它应该是这样的:
方法调用是一个契约,正如其他人所说,你需要指定你的
ConsumerClass
实际上可以的最通用的类型使用。您可能想阅读里氏替换原则:http://en.wikipedia.org/wiki/Liskov_substitution_principle< /a>.在这种情况下,虽然 IMutableSomething 可以替代 ISomething,但反之则不然。
I think your interfaces are fine, but in your consumer code it should look like this:
The method call is a contract, and as others have said you need to specify the most general type that your
ConsumerClass
can actually use. You might want to read up on Liskov substitution principle: http://en.wikipedia.org/wiki/Liskov_substitution_principle.In this case, while IMutableSomething can substitute for ISomething, the inverse is not true.
这实际上并不是接口的正确使用方式;接口使您不必关心实现是什么,您只需使用定义的属性和方法即可。如果您需要“设置”具有仅获取接口的内容,则不应将该接口作为参数传递。
在这种情况下,如果您必须使用接口,请在接口上定义一个 set 方法(或以不同的方式实现属性)
,然后简单地让不可变接口对值不执行任何操作(或抛出异常)。
This isn't really the proper use of an interface; the interface is so that you don't care what implementation is, you simply use the defined properties and methods. If you need to 'set' something that has a get only interface, you should not be passing the interface as a parameter.
In this kind of situation, if you MUST go with an interface, define a set method on your interface (or implement the property differently)
And then simply have the immutable interfaces do nothing with the value (or throw an exception).