Переменная частного назначения только для использования в свойстве - PullRequest
3 голосов
/ 08 февраля 2012

Возможно ли иметь переменную, которая является переменной экземпляра в классе, но доступ к которой может получить только конкретное свойство?

Я довольно часто создаю "самосоздавающиеся" свойства, подобные так ...

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 ]

5 голосов
/ 08 февраля 2012

Я согласен, что было бы неплохо иметь языковую особенность постоянных локальных - то есть переменных, чьи времена жизни основаны на времени жизни экземпляра, но чьи области действия (область текста программы, в которой разрешен доступ к переменной по имени) являются локальными.Было бы неплохо иметь «статические» локальные объекты, как это делают некоторые языки.

К сожалению, это не является особенностью C #, и мы не планируем добавлять ее.Приятно иметь, но приятно иметь недостаточно хорошо, чтобы оправдать расходы, или отложить или отменить функцию «лучше иметь».

Это просто «приятно иметь», потому что, конечно, если у вас естьчастное поле, это уже частная реализация класса.Если вы не хотите, чтобы он использовался вне свойства, то не пишите код, который использует его вне свойства .Если кто-то из ваших коллег попытается сделать это, опустите их при проверке кода.

Я подумал, что могу добавить: Будьте очень осторожны при написании методов получения свойств, которые изменяют состояние. По умолчанию методы получения свойств оцениваются при просмотре объекта в отладчике, и может очень сбивать с толку что-то отлаживать и иметь отладчик , изменяющий значения полей только потому, что вы осмотр объекта .

1 голос
/ 09 февраля 2012

Ваша текущая реализация выглядит для меня сломанной.

var x=obj.Location;
x.Latitude = 1;
Console.WriteLine(x.Latitude);//1
var y=obj.Location;
Console.WriteLine(x.Latitude);//WTF it changed

Я рекомендую сделать IWGSLocation неизменным или модифицировать его только при создании, в зависимости от того, какую семантику вы хотите.

1 голос
/ 08 февраля 2012

Тот факт, что класс может получить к нему доступ, не обязательно является недостатком. Он все еще логически заключен в том же объекте.

То, что вы после , невозможно так, как вы хотите. Переменные-члены видны во всех областях класса, а локальные переменные ограничены определенной областью.

То, что вы могли бы вместо этого сделать, это поместить объект в класс контейнера. Этот класс является вашей переменной-членом. Возвращая 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; }
}

Имейте в виду, это было скомпилировано головой! : -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...