如何通过接口继承在C#中重新定义属性?

如何通过接口继承在C#中重新定义属性?,c#,properties,interface,redefine,explicit-interface,C#,Properties,Interface,Redefine,Explicit Interface,我有一个接口“IBase”,它指定了一个可为null的int。后面的接口“IDerived”隐藏了可为null的int,并将其“重新定义”为不可为null interface IBase { int? Redefineable { get; set; } } interface IDerived : IBase { new int Redefineable { get; set; } } 实现这些接口的类必须显式实现隐藏属性,但是它是私有的,因此客户端无法看到它 class

我有一个接口“IBase”,它指定了一个可为null的int。后面的接口“IDerived”隐藏了可为null的int,并将其“重新定义”为不可为null

interface IBase
{
    int? Redefineable { get; set; }
}

interface IDerived : IBase
{
    new int Redefineable { get; set; }
}
实现这些接口的类必须显式实现隐藏属性,但是它是私有的,因此客户端无法看到它

class TheClass : IDerived
{
    public int Redefineable { get; set; }
    int? IBase.Redefineable { get; set; }
}
然而,即使它是私有财产,我仍然可以通过IBase接口访问它

var o = new TheClass();
o.Redefineable = 1; // ok

var hack = o as IBase;
hack.Redefineable = null; // uh!
这似乎违反了C#访问修饰符,但不管怎样,这都不是我重新定义(而不仅仅是隐藏)属性的真正想法。这是正确的,因为它可以满足您的要求,获得一个具有可空int的IBase接口,但这对客户端来说是不直观的,客户端可能会修改属性的错误版本

我真正想要的是,如果客户端访问IBase.redefineable,那么它的行为就好像访问iderive.redefineable属性,类的“real”属性一样。这样,它实际上被重新定义,就像在层次结构中一样

class TheClass : IDerived
{
    public int Redefineable { get; set; }
    int? IBase.Redefineable { 
        get { 
            // redirect to redefined property
            return this.Redefineable; 
        }
        set
        {
            // stop client setting it to null
            if (!value.HasValue)
                throw new InvalidOperationException();

            // redirect to redefined property
            this.Redefineable = value.Value;
        }
    }
}
这感觉就像是一个黑客,几乎就像我错过了什么,所以我想问一下,是否有人知道一个更好的/替代的方法来实现可重新定义的属性

然而,即使它是私有财产,我仍然可以通过IBase接口访问它


这不是私人财产。它只是一个使用显式接口实现的属性。这意味着它通过接口是公共的,但只能通过接口使用。显式接口实现主要是为了使实现“矛盾的”接口变得可行,以及用于“阻止”(但不是禁止)某些接口方法的使用。这并不是要给人一种会员根本不存在的印象

从根本上说,听起来您不应该在这里使用继承-如果您不希望某些东西能够充当
IBase
,那么您不应该从
IBase
继承

然而,即使它是私有财产,我仍然可以通过IBase接口访问它


这不是私人财产。它只是一个使用显式接口实现的属性。这意味着它通过接口是公共的,但只能通过接口使用。显式接口实现主要是为了使实现“矛盾的”接口变得可行,以及用于“阻止”(但不是禁止)某些接口方法的使用。这并不是要给人一种会员根本不存在的印象


从根本上说,听起来你不应该在这里使用继承-如果你不想让某个东西能够充当
IBase
,你不应该从
IBase

继承,我认为你需要重温多态性是如何工作的。如果您有一个
IBase
,并且您正在使用它的属性,那么它将是
IBase
如何定义它的。如果你有一个
IDerived
并且你正在使用它的属性,那么它将是
IDerived
如何定义它的。这就是它的工作原理。明确的接口实现不是通常意义上的
private
。因此,不允许为它们指定
private
修饰符。使用
new
修饰符隐藏成员(此处为属性)并不是“重新定义”它。它只是介绍另一个看起来相同的成员。这很少是一件好事。通过向上转换到定义原始成员的类型(此处为基本接口),原始成员不会被删除,并且始终可以使用。显式接口实现只是为了解决由于必须实现两个同名成员而导致的歧义问题。这不是访问限制。我认为您需要重新了解多态性是如何工作的。如果您有一个
IBase
,并且您正在使用它的属性,那么它将是
IBase
如何定义它的。如果你有一个
IDerived
并且你正在使用它的属性,那么它将是
IDerived
如何定义它的。这就是它的工作原理。明确的接口实现不是通常意义上的
private
。因此,不允许为它们指定
private
修饰符。使用
new
修饰符隐藏成员(此处为属性)并不是“重新定义”它。它只是介绍另一个看起来相同的成员。这很少是一件好事。通过向上转换到定义原始成员的类型(此处为基本接口),原始成员不会被删除,并且始终可以使用。显式接口实现只是为了解决由于必须实现两个同名成员而导致的歧义问题。这不是访问限制。好的,谢谢您提供有关私人/公共问题的信息。我确实希望它作为一个iBASE——除了访问一个属性以外的所有其他情况,显然这是问题的简化例子,在真正的代码中,在一个层次结构中有30个接口来实现多重继承,相当于IBase在中间的某个地方,它也有其他属性。我会说它是一个IBase,但是有一个重新定义的属性。我不知道如何更好地实现它,因此我提出了一个问题。@MarkB:但是一个与IBase类似但具有不同属性类型的接口根本不是IBase。也许你应该在它自己的接口中有这个属性,所以你可以有两个可选的接口,这取决于它的类型是
int?
还是
int
…当然,但是我所做的就是在该接口的实现中添加一个规则,所以尽管它被定义为可为null,尝试将值设置为null(在某些实现类上)将导致异常。如果将int设置为数字5,则会引发异常,这与int有什么不同吗?@MarkB:是的-您正在尝试更改