0

嗨,我以为我正在理解这些概念,但我不确定了。

假设我有以下内容:

界面

public interface IUnit
{
    DateTime CreatedDateTime { get; set; }
}

基类

public abstract class UnitBase : IUnit
{
    public virtual DateTime CreatedDateTime
    {
        get;
        protected set;
    }
    DateTime IUnit.CreatedDateTime
    {
        get
        {
            return CreatedDateTime;
        }
        set
        {
            CreatedDateTime = value;
        }
    }
}

然后,我有另一个继承自 UnitBase 的类

public class NewClass : UnitBase
{
}

NewClass 包含 CreatedDateTime 的属性,因为它继承自 UnitBase,并且由于 NewClass 没有覆盖它,我想它仍然具有 set 的受保护访问器。

所以如果我要创建一个 NewClass 的新实例:

NewClass obj = new NewClass();
obj.CreatedDateTime = DateTime.Now;  //This is not allowed 

但是为什么我可以将 obj 转换为 IUnit 并对其进行修改?

//like this
((IUnit)obj).CreatedDateTime = DateTime.Now  //Allowed?

我认为受保护的集只能在它声明的类(UnitBase)和从它继承的类(NewClass)的范围内设置它的值。那么我怎么能像那样投射和修改它呢?如果允许,保护集的意义何在?我不太明白这里发生了什么。有人可以向我解释吗?

编辑:对不起,我已经修改了代码,现在应该可以编译了。那么,如果我能够将它转换为 IUnit 并更改值,那不会破坏受保护集的目的吗?我可以更改界面中的修饰符,以便我无法转换为 IUnit 并修改值吗?

4

3 回答 3

1

接口 IUnit 指定了一个设置器。这意味着 setter 是公共的,这就是为什么您可以通过强制转换为 IUnit 来设置它的原因。

如果您希望 IUnit 的实现能够为 set 指定自己的访问修饰符,只需指定 get 必须在接口中公开,如下所示:

public interface IUnit
{
    DateTime CreatedDateTime { get; }
}
于 2013-04-26T17:15:41.170 回答
0

就您将and强制obj转换为,编译器将其视为 an,因此您可以设置and 没有任何错误或特殊之处。IUnitIUnitIUnitCreateDateTime

此外,您的代码将无法编译。因为UnitBase没有实施IUnit. 要达到您正在寻找的内容,您可以编辑UnitBase如下:

public class UnitBase : IUnit
{
    public DateTime CreateDateTime { get; protected set; }

    DateTime IUnit.CreatedDateTime
    {
        get; set;
    }
}
于 2013-04-26T17:14:20.293 回答
0

该接口定义了一个合同,合同说 CreateDateTime 有一个公共的 get/set。一旦您转换了该对象,它就会将该对象视为接口,并且该接口有一个公共集。

如果不是这种情况,任何采用 IUnit 的函数都必须动态确定对象的真实类型,然后查看是否应用了访问修饰符。这意味着静态链接不会在您传入虚拟对象时应用,并且派生的子对象可能会改变接口的含义。想想当您谈论单独构建程序集时这意味着什么

于 2013-04-26T17:18:45.820 回答