是否可以拥有一个变量,它是一个类中的实例变量,但只能由特定属性访问?
我经常创建“自我创造”属性,如此......
private IWGSLocation _location;
public IWGSLocation Location
{
get
{
_location = _location ?? new WGSLocation();
_location.Latitude = Latitude.GetValueOrDefault(0);
_location.Longitude = Longitude.GetValueOrDefault(0);
return _location;
}
}
这意味着我不会重新创建一个新的WGSLocation
(或者我需要的任何其他类型的对象,创建起来可能很昂贵,或者每次我可能只需要创建一次)进入酒店。缺点是我的类可以访问_location变量。但是我真的不想要它,所以如果有任何方法可以使用只能在属性本身内使用的实例变量吗?
我正在考虑这些问题......
public IWGSLocation Location
{
get
{
WGSLocation _location = _location ?? new WGSLocation();
_location.Latitude = Latitude.GetValueOrDefault(0);
_location.Longitude = Longitude.GetValueOrDefault(0);
return _location;
}
}
答案 0 :(得分:5)
我同意持久本地是一个很好的语言功能 - 也就是说,生命周期基于实例生命周期但其的变量>范围(程序文本的区域,通过名称访问变量是合法的)是本地的。像某些语言一样,拥有“静态”本地人也会很不错。
可悲的是,这不是C#的功能,我们也没有计划添加它。很高兴拥有,但很高兴不足以证明费用,或推迟或取消“更好的”功能。
它只是“很高兴”,因为当然如果你有一个私有字段,它已经是该类的私有实现细节。如果您不希望在属性外使用它,那么不会编写在属性外使用它的代码。如果你的一个同事试图这样做,那就把它们放在代码审查中。
我想我可能会补充:在编写改变状态的属性getter时要非常小心。默认情况下,在查看调试器中的对象时会对属性getter进行求值,并且它可以非常混淆进行调试,让调试器更改字段值只是因为你正在检查一个对象。
答案 1 :(得分:1)
班级可以访问它的事实不一定是缺点。它仍然在逻辑上封装在同一个实体中。
按照您希望的方式 之后 。成员变量在类的所有区域都可见,局部变量仅限于其定义的范围。
您可以做的是将位置包装在容器类中。这个类是你的成员变量。返回IWGSLocation
时,只需深入查看容器类:
public class LocationContainer
{
public IWGSLocation InnerLocation { get; private set; }
public void SetLocation(WGSLocation loc)
{
InnerLocation = loc;
}
}
private readonly LocationContainer _container = new LocationContainer();
public IWGSLocation Location
{
get
{
if (_container.InnerLocation == null)
{
_container.SetLocation(...);
}
return _container.InnerLocation;
}
}
这不会阻止课程触及_container
,但它会让其他开发人员在他们这样做之前三思而后行,如果没有明确地调用SetLocation
,他们将无法意外地改变位置。
您甚至可以在容器的SetLocation
中设置一次保护。
更新:我实际上在这里使用了懒惰的类,比如:
private readonly Lazy<IWGSLocation> _location = new Lazy<IWGSLocation>(()
=>
{
var l = new WGSLocation();
l.Latitude = Latitude.GetValueOrDefault(0);
l.Longitude = Longitude.GetValueOrDefault(0);
return l;
});
public IWGSLocation Location
{
get { return _location.Value; }
}
请注意,这是头编译的! : - )
答案 2 :(得分:1)
你当前的实现对我来说很糟糕。
var x=obj.Location;
x.Latitude = 1;
Console.WriteLine(x.Latitude);//1
var y=obj.Location;
Console.WriteLine(x.Latitude);//WTF it changed
我建议让IWGSLocation
不可变,或者只在创建时修改它,具体取决于你想要的语义。