私有范围的变量仅用于属性内

时间:2012-02-08 11:29:22

标签: c# properties

是否可以拥有一个变量,它是一个类中的实例变量,但只能由特定属性访问?

我经常创建“自我创造”属性,如此......

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;
    }
}

3 个答案:

答案 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不可变,或者只在创建时修改它,具体取决于你想要的语义。