[英]What's the best way expose a mutable interface over an immutable one?
I wonder what's the best practice in C# regarding mutable / immutable interfaces.我想知道 C# 关于可变/不可变接口的最佳实践是什么。
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.
但是,当我需要更改 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以这种方式工作使我能够轻松测试 ConsumerClass 并打破 ISomething 与其实现之间的任何依赖关系
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.埃里克·G。
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)在这种情况下,如果您必须使用接口 go,请在您的接口上定义一个 set 方法(或以不同的方式实现该属性)
public interface ISomething
{
string Name { get; set;}
void SetName(string newValue);
}
// Choose one of these methods to implement; both is overkill
public class SomethingElse : ISomething
{
protected string _internalThing = string.Empty;
public string Name
{
get { return _internalThing; }
set { throw new InvalidOperationException(); }
}
public void SetName(string newValue)
{
throw new InvalidOperationException();
}
}
And then simply have the immutable interfaces do nothing with the value (or throw an exception).然后简单地让不可变接口对值不做任何事情(或抛出异常)。
I think your interfaces are fine, but in your consumer code it should look like this:我认为你的接口很好,但在你的消费者代码中它应该是这样的:
public class ConsumerClass{
// Just take IMutableSomething
public void DoSomethingOnName(IMutableSomething o) {
o.Name = "blah";
}
}
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.方法调用是一种契约,正如其他人所说,您需要指定您的
ConsumerClass
实际可以使用的最通用类型。 You might want to read up on Liskov substitution principle: http://en.wikipedia.org/wiki/Liskov_substitution_principle .您可能想阅读 Liskov 替换原则: http://en.wikipedia.org/wiki/Liskov_substitution_principle 。
In this case, while IMutableSomething can substitute for ISomething, the inverse is not true.在这种情况下,虽然 IMutableSomething 可以替代 ISomething,但反之则不成立。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.