嗨,我以为我理解这些概念,但我不确定了。
假设我有以下内容:
接口
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?
我认为protected set只能在它声明的类(UnitBase)和从它继承的类(NewClass)的范围内设置它的值。那么为什么我可以投射并修改它呢?如果允许,保护集的重点是什么?我不太明白这里发生了什么。有人可以向我解释一下吗?
编辑:Sry我修改了代码,现在应该编译。那么,如果我能够将它转换为IUnit并更改值,那么这不会破坏受保护集的目的吗?我可以更改界面中的修饰符,这样我就无法转换为IUnit并修改值吗?
答案 0 :(得分:1)
IUnit接口指定了一个setter。这意味着setter是公共的,这就是允许你通过强制转换为IUnit来设置它的原因。
如果您希望IUnit的实现能够为set指定自己的访问修饰符,只需指定get必须在接口中公开,如下所示:
public interface IUnit
{
DateTime CreatedDateTime { get; }
}
答案 1 :(得分:0)
如果您将obj
转换为IUnit
和IUnit
,编译器会将其视为IUnit
,因此您可以设置CreateDateTime
和没有什么是错的或特别的。
此外,您的代码将无法编译。因为UnitBase
没有实现IUnit
。要找到您要找的内容,您可以按以下方式修改UnitBase
:
public class UnitBase : IUnit
{
public DateTime CreateDateTime { get; protected set; }
DateTime IUnit.CreatedDateTime
{
get; set;
}
}
答案 2 :(得分:0)
接口定义了一个合同,该合同表明CreateDateTime具有公共get / set。一旦你转换了该对象,它就会将对象视为接口,并且接口具有公共集。
如果不是这种情况,任何采用IUnit的函数都必须动态确定对象的真实类型,然后查看是否应用了访问修饰符。这意味着静态链接不会在您传入虚拟对象时发生,并且派生的子项可能会更改接口的含义。想想当你谈论单独构建程序集时会有什么意义