Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在返回派生类型的派生接口中隐藏属性是否可以接受? TL;博士_C#_Interface_Covariance_Method Hiding - Fatal编程技术网

C# 在返回派生类型的派生接口中隐藏属性是否可以接受? TL;博士

C# 在返回派生类型的派生接口中隐藏属性是否可以接受? TL;博士,c#,interface,covariance,method-hiding,C#,Interface,Covariance,Method Hiding,在接口中隐藏属性,以便更改其声明以返回原始属性的派生类型,这有什么错? 我相信这肯定是以前问过的,但我找不到,我为这个冗长的问题道歉 假设我有这种情况: public interface A { B TheB{get;} } public interface MoreSpecificA : A { MoreSpecificB TheMoreSpecificB{get;} } public interface B{...} public interface MoreSpeci

在接口中隐藏属性,以便更改其声明以返回原始属性的派生类型,这有什么错?

我相信这肯定是以前问过的,但我找不到,我为这个冗长的问题道歉

假设我有这种情况:

public interface A
{
    B TheB{get;}
}

public interface MoreSpecificA : A
{
    MoreSpecificB TheMoreSpecificB{get;}
}

public interface B{...}

public interface MoreSpecificB:B{...}
我希望
MoreSpecificA
的用户能够访问B,这是一个
MoreSpecificA
。他们可以通过调用
b
并强制转换它来实现这一点,或者他们可以调用方法
更具体的b
。我也可以这样声明
morespecica

public interface MoreSpecificA : A
{
    new MoreSpecificB TheB{get;}
}
因此,现在他们可以使用相同的方法返回a
moresspecific b

使用
new
隐藏一个方法会让我的牙齿感到不安,那么为什么这是个坏主意呢?在这里这样做似乎是合理的

在大多数情况下,我看到的一般建议似乎是使用泛型,但这似乎有一个问题,如果我有一个
morespecica
,并且我想用一个方法返回它,该方法将返回类型声明为
a
,那么我必须有
morespecica
扩展
a
,这在访问
morespecica
实例上的
b
时会产生歧义知道你是想要更具体的A.TheB还是
A.TheB

public interface ABase<T> where T : B
{
    T TheB{get;}
}

public interface A : ABase<B>
{        
}

public interface MoreSpecificA : ABase<MoreSpecificB>,A
{        
}

public class blah
{
    public A GetA(MoreSpecificA specificA)
    {
        return specificA; //can't do this unless MoreSpecificA extends A 
    }

    public B GetB(MoreSpecificA specificA)
    {
        return specificA.TheB; //compiler complains about ambiguity here, if MoreSpcificA extends A
    }
}
还有我的班级

public class blah
{
    public ABase<B> GetA(MoreSpecificA specificA)
    {
        return specificA; 
    }

    public B GetB(MoreSpecificA specificA)
    {
        return specificA.TheB; //compiler complains about ambiguity here
    }
}
公共类废话
{
公共ABase GetA(更具体)
{
返回特定值a;
}
公共B GetB(更具体)
{
return specificA.TheB;//编译器在这里抱怨不明确
}
}
那我就两全其美了。此解决方案的适用性是否取决于
A
是否为
ABase
添加了任何内容

或者,我最初的计划是将方法隐藏在派生类型中,以返回原始方法的派生类型,这样可以吗

或者,我最初的计划是将方法隐藏在派生类型中,以返回原始方法的派生类型,这样可以吗

只要意思完全一样,我想没关系。在标准库中可以看到类似的内容,例如(返回
IDbCommand
)和(返回
SqlCommand

在这种情况下,它对
IDbConnection
版本使用显式接口实现,但原理相同

您还可以在
IEnumerator.Current
vs
IEnumerator.Current
IEnumerable.GetEnumerator()
vs
IEnumerable.GetEnumerator()
中看到它


我只会在弱类型方法的实现只返回调用强类型方法的结果的情况下使用它,不过使用隐式转换。当他们真正开始做不同的事情时,以后就很难再去思考了。

谢谢Jon。在我的例子中,所讨论的对象被用作密钥。在系统中,所有键都实现了
IKey
,带有一些更具体的键接口,这些接口用作类型类键的标记。在所有实现类中,它们都有一个具体类型的键,所有返回IKey(或的派生)的接口方法的实现都将返回同一个实例。@SamHolder:听起来不错。基本上,这弥补了.NET中协变返回类型的不足:(在我看来,它们只是遇到了一个限制,没有多重继承创建。也许一些工厂或构建器模式可以节省时间。
public class blah
{
    public ABase<B> GetA(MoreSpecificA specificA)
    {
        return specificA; 
    }

    public B GetB(MoreSpecificA specificA)
    {
        return specificA.TheB; //compiler complains about ambiguity here
    }
}