仅在属性中使用的私有范围的变量
本文关键字:范围 变量 属性 | 更新日期: 2023-09-27 18:23:40
是否可以在类中有一个实例变量,但只能由特定属性访问?
我经常创建"自我创建"属性,比如。。。
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;
}
}
我同意拥有持久本地是一个很好的语言功能,也就是说,生存期基于实例的生存期,但作用域(按名称访问变量是合法的程序文本区域)是本地的变量。像一些语言一样,拥有"静态"本地语言也会很好
遗憾的是,这不是C#的一个功能,我们也没有添加它的计划。拥有它很好,但拥有它还不足以证明费用的合理性,也不足以推迟或取消"拥有更好"的功能。
它只是"很好拥有",因为如果你有一个私有字段,它已经是类的私有实现细节了。如果您不希望它在属性之外使用,那么就不要编写在属性外部使用它的代码。如果你的一个同事试图这样做,在代码审查中对他们进行严厉打击。
我想我可以补充一点:在编写改变状态的属性getter时要非常小心默认情况下,属性getter是在调试器中查看对象时评估的,如果调试某个对象并让调试器更改字段值,这可能会让非常困惑,因为正在检查对象。
类可以访问它并不一定是一个缺点。它仍然在逻辑上封装在同一个实体中。
您在之后的内容不可能按照您希望的方式。类的所有区域都可以看到成员变量,并且局部变量被限制在其定义的范围内。
相反,您可以将位置封装在一个容器类中。此类是您的成员变量。返回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; }
}
请注意,这是头编的:-)
在我看来,您当前的实现已经崩溃。
var x=obj.Location;
x.Latitude = 1;
Console.WriteLine(x.Latitude);//1
var y=obj.Location;
Console.WriteLine(x.Latitude);//WTF it changed
我建议将IWGSLocation
设置为不可变的,或者只在创建时对其进行修改,这取决于您想要的语义。