开发者

What's the best way expose a mutable interface over an immutable one?

开发者 https://www.devze.com 2023-03-03 10:56 出处:网络
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 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 an开发者_如何转开发d 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.


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. 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.


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)

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).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号