给出以下内容:
class A : B {}
interface I
{
B TheObject {get;set;}
}
我能以某种方式这样做吗?
class C : I
{
public A TheObject {get;set;}
}
请注意,接口具有基类,实现具有子类。
答案 0 :(得分:12)
试一试
class C : I
{
public A TheObject {get;set;}
B I.TheObject
{
get { return A; }
set { A = value as A; }
}
}
您可能需要根据需要修改B setter。以这种方式实现接口具有以下结果。处理类型为C的变量时,您将无法访问B TheObject。如果需要,您需要声明一个I变量并将其分配给您的C var。以这种方式实现我称为显式实现。
例如
C c = new C();
A a = c.TheObject; // TheObject is an A
I i = c;
B b = i.TheObject;
答案 1 :(得分:2)
您无法执行此操作,因为接口实现的返回类型必须匹配。但是,我为什么不能这样做的理由是错误的(正如评论中所指出的那样)。您必须匹配签名,但您可以从C ...返回一个新的A
public class C : I
{
public B TheObject { get { return new A(); } set {} }
}
答案 2 :(得分:1)
答案 3 :(得分:1)
不。编译器会抱怨类型不匹配。
另外,我将不同意保罗:我认为差异不会对你的情况有所帮助。 看看Skeet对方差here所说的内容。
答案 4 :(得分:1)
不,假设如下:
class D : B {}
C c = new C();
c.TheObject = new D(); // error. D is not A, A is not D
使用上面的类,我仍然可以将D
用于实现接口I
的对象,但我们假设我想将TheObject
实例的C
属性设置为D
的实例。我不能,因为D
和A
是兄弟姐妹。它们都继承自同一个类,因为它们在接口中就可以了,但是声明你期望A
困惑编译器。 A的实例不是D的实例,但A和D的实例都是B的实例。
此规则遵循Liskov Substitution Principle。
P.S。我要感谢Troels Knak-Nielsen对这一微妙之处的开放态度。
答案 5 :(得分:0)
你所想的是协方差/逆变,但即使使用C#4.0,这也行不通。如果您只有对接口的引用,它仍然需要可用。
getter可以工作,因为A也是B,但是setter不能工作,因为实现需要A,而接口允许你将TheObject设置为B. 通常,返回值可以是子类型,参数可以是具有协方差/逆变的基类型。但仅限于C#4.0。
答案 6 :(得分:0)
编译:
class B { }
class A : B { }
interface I<T> where T : B
{
T TheObject { get; set; }
}
class C : I<A>
{
public A TheObject { get; set; }
}
但我认为这不是你想要的?