use*_*789 6 c# interface new-operator
我理解"new"关键字如何隐藏派生类中的方法.但是,它对实现使用关键字的接口的类有什么影响?
考虑这个例子,我决定通过使其属性读/写来扩展接口.
public interface IReadOnly {
string Id {
get;
}
}
public interface ICanReadAndWrite : IReadOnly {
new string Id {
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以做到这样的事情:
public IReadOnly SomeMethod() {
// return an instance of ICanReadAndWrite
}
Run Code Online (Sandbox Code Playgroud)
这是不好的设计吗?它会导致我的类实现ICanReadAndWrite的问题吗?
编辑: 这是一个人为的例子,说明我为什么要这样做:
假设我有一个返回IShoppingCartItemReadWrite的工厂类.然后,我可以有一个服务层来操作它的价格,更改东西等.然后,我可以将这些对象作为IShoppingCartItemReadOnly传递给某种不会改变它们的表示层.(是的,我知道它在技术上可以改变它们 - 这是一个设计问题,而不是安全性等)
Meh*_*ari 19
这不是一个特别糟糕的主意.您应该知道实现者可以(如果它隐式实现接口,那么单个读/写属性可以满足两个接口)提供两个不同的实现:
class Test : ICanReadAndWrite {
public string Id {
get { return "100"; }
set { }
}
string IReadOnly.Id {
get { return "10"; }
}
}
Test t = new Test();
Console.WriteLine(t.Id); // prints 100
Console.WriteLine(((IReadOnly)t).Id); // prints 10
Run Code Online (Sandbox Code Playgroud)
顺便说一下,通常,new继承修饰符除了告诉编译器关闭并且不抛出"你正在隐藏该成员"警告之外什么都不做.省略它将对编译的代码没有影响.
您不应该基于IReadOnly实现ICanReadWrite,而是将它们分开.
即.像这样:
public interface IReadOnly
{
string Id
{
get;
}
}
public interface ICanReadAndWrite
{
string Id
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个使用它们的类:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,类中的相同属性可以支持这两个接口.
请注意,根据注释,获得稳健解决方案的唯一方法是使用包装器对象.
换句话说,这不好:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
因为调用者可以这样做:
ICanReadWrite rw = obj.AsReadOnly() as ICanReadWrite;
rw.Id = "123";
Run Code Online (Sandbox Code Playgroud)
要获得强大的解决方案,您需要一个包装器对象,如下所示:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return new ReadOnly(this);
}
}
public class ReadOnly : IReadOnly
{
private IReadOnly _WrappedObject;
public ReadOnly(IReadOnly wrappedObject)
{
_WrappedObject = wrappedObject;
}
public string Id
{
get { return _WrappedObject.Id; }
}
}
Run Code Online (Sandbox Code Playgroud)
这将工作,并且健壮,直到调用者使用反射的点.