Более частный, чем частный? (C#)

Может быть ниже кода справки Я использую jquery:

<table id="tableId">
<tr>
<td align="center"><input type="checkbox" name="chkToPay"  value="0"></td>

<td align="center"><input type="checkbox" name="chkToPay"  value="1"></td>

<td align="center"><input type="checkbox" name="chkToPay"  value="2"></td>

<td align="center"><input type="checkbox" name="chkToPay" value="3"></td>
</tr>


$(document).on("click", '#tableId tbody :checkbox[name="chkToPay"]', function(event) {
var currentRows = $('#tableId');

$.each(currentRows, function() {
        $(this).find(':checkbox[name=chkToPay]').each(function() {
            if($(this). prop("checked") == true){
                var parentTr = $(this).parents("tr");
                $(this).prop('checked', true);
        alert($(this).val());
        // if you need text from another td you can access by below line
                //alert(parentTr.children("td").eq(0).text());

            }
        });
    });
        });
25
задан Jason Plank 22 November 2011 в 20:59
поделиться

19 ответов

ИМХО, он не используется, потому что:

  • Класс должен доверять себе
  • Если ваш класс становится настолько большим, что одна часть не знает другой, он должен быть разделен.
  • Если логика, лежащая в основе этого свойства, несколько сложнее, рассмотрите возможность инкапсулировать его в свой собственный тип.
41
ответ дан Stefan Steinegger 28 November 2019 в 17:36
поделиться

Новый класс Lazy в .net 4.0

обеспечивает поддержку нескольких распространенных шаблонов ленивой инициализации

По моему опыту, это самая распространенная причина, по которой я хочу правильно оберните поле в приват, так что хорошо решает общий случай. (Если вы еще не используете .Net 4, вы можете просто создать свой собственный класс «Lazy» с тем же API, что и в версии .Net 4.)

См. , это и . это и это для деталей использования класса Lazy.

0
ответ дан Ian Ringrose 28 November 2019 в 17:36
поделиться

Если вы используете компилятор C # 3.0, вы можете определить свойства, которые имеют сгенерированные компилятором вспомогательные поля, например:

public int MyInt { get; set; }

Это будет означать, что есть только один способ доступа к свойству. не означает, что вы можете получить доступ только к полю, но это означает, что нет ничего, кроме свойства для доступа.

0
ответ дан Aaron Powell 28 November 2019 в 17:36
поделиться

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

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

1
ответ дан tvanfosson 28 November 2019 в 17:36
поделиться

Это невозможно сделать в стандартном C #, однако вы можете

  • определить пользовательский атрибут, например, OnlyAccessFromProperty

  • написать свой код. как

    [OnlyAccessFromProperty(Name)]
    String name
    
    Name 
    {
       get{return name;}
    }
    
    etc …
    
  • Затем напишите пользовательское правило для FxCop (или другого средства проверки)

  • Добавьте FxCop в свою систему сборки поэтому, если ваше пользовательское правило обнаружит ошибку, сборка будет неудачной.

Нужен ли нам набор стандартных настраиваемых правил / атрибутов для реализации таких патентов общего дизайна без необходимости расширять C #

3
ответ дан Jason Plank 28 November 2019 в 17:36
поделиться

Возможно, хранилище резервных копий свойств аналогично тому, как WPF хранит свойства ?

. Таким образом, вы можете иметь:

Dictionary<string,object> mPropertyBackingStore = new Dictionary<string,object> ();

public PropertyThing MyPropertyThing
{
    get { return mPropertyBackingStore["MyPropertyThing"] as PropertyThing; }
    set { mPropertyBackingStore["MyPropertyThing"] = value; }
}

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

P.S. Вы даже можете использовать инфраструктуру свойств зависимостей из WPF ...
P.P.S. Очевидно, что это повлечет за собой затраты на кастинг, но это зависит от ваших потребностей - если производительность критична, возможно, это не решение для вас.
P.P.P.S Не забудьте инициализировать резервное хранилище! (;

РЕДАКТИРОВАТЬ:

Фактически, если вы измените свойство значения, сохраненное на объект хранения свойства (например, с помощью шаблона Command)), вы можете обработка в объекте команды ... просто мысль.

3
ответ дан Kieron 28 November 2019 в 17:36
поделиться

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

public class A
{
   class FieldsForA
   {
      private int number;
      public int Number
      {
         get
         {
           //TODO: Extra logic.
           return number;
         }
         set
         {
           //TODO: Extra logic.
           number = value;
         }
      }
   } 
   FieldsForA fields = new FieldsForA();

   public int Number
   {
      get{ return fields.Number;}
      set{ fields.Number = value;}
   }       
}

Это просто обеспечивает уровень обструкции. Основная проблема доступа к частным резервным полям все еще существует во вложенном классе. Однако код в классе A не может получить доступ к этим закрытым полям вложенного класса FieldForA. Он должен пройти через общественную собственность.

5
ответ дан Mehmet Aras 28 November 2019 в 17:36
поделиться

В C # такого обеспечения нет.

Однако я бы назвал закрытые переменные по-разному (например, m_something или просто _something), чтобы легче было определить его при использовании.

5
ответ дан Josip Medved 28 November 2019 в 17:36
поделиться

Вы МОЖЕТЕ сделать это, используя замыкание над локальным в конструкторе (или другой функцией инициализации). Но это требует значительно больше работы, чем подход вспомогательного класса .

class MyClass {
  private Func<Foo> reallyPrivateFieldGetter;
  private Action<Foo> reallyPrivateFieldSetter;
  private Foo ReallyPrivateBackingFieldProperty {
    get { return reallyPrivateFieldGetter(); }
    set { reallyPrivateFieldSetter(value); }
  }

  public MyClass() {
    Foo reallyPrivateField = 0;
    reallyPrivateFieldGetter = () => { return reallyPrivateField; }
    reallyPrivateFieldSetter = v => { reallyPrivateField = v; };
  }
}

Я подозреваю, что базовый тип поля Foo должен быть эталонным классом, поэтому два замыкания создаются для одного объекта.

7
ответ дан Community 28 November 2019 в 17:36
поделиться

Нет встроенного способа делать то, что вы хотите делать, но по звукам вещей вам нужен еще один уровень абстракции между вашим классом и этим значением.

Создайте отдельный класс и поместите туда элемент, тогда ваш внешний класс содержит новый класс, и вы можете получить к нему доступ только через его свойства.

20
ответ дан Luke Girvin 28 November 2019 в 17:36
поделиться

Я бы посчитал это мерзким взломом и попытался бы избежать его, если это возможно, но ...

Вы можете пометить вспомогательное поле как устаревшее, чтобы компилятор генерировал предупреждение при попытке доступа к нему, а затем подавляло это предупреждение для свойства getter / setter.

Коды предупреждений, которые вам нужно подавить: CS0612 для простого атрибута Obsolete и CS0618 , если у атрибута есть пользовательское сообщение.

[Obsolete("Please don't touch the backing field!")]
private int _backingField;

public int YourProperty
{
    #pragma warning disable 612, 618
    get { return _backingField; }
    set { _backingField = value; }
    #pragma warning restore 612, 618
}
22
ответ дан LukeH 28 November 2019 в 17:36
поделиться

В C # нет языковой функции для этого. Однако вы можете полагаться на соглашения об именах, аналогичные языкам, которые вообще не имеют частных свойств. Добавьте к своим более частным именам переменных префикс _p_, и вы будете совершенно уверены, что случайно не наберете его.

2
ответ дан Malte Clasen 28 November 2019 в 17:36
поделиться

Используйте тип конструкции «очень конфиденциальный»

Пример:

veryprivate void YourMethod()
{

  // code here
}
-1
ответ дан 28 November 2019 в 17:36
поделиться

Я согласен с общим правилом что класс должен доверять себе (и, следовательно, всем, кто кодирует внутри класса). Жалко, что поле раскрывается через интеллект.
К сожалению, размещение [EditorBrowsable (EditorBrowsableState.Never)] не работает в этом классе (или действительно в сборке (1))

В Visual C # EditorBrowsableAttribute не подавляет члены из класса в та же сборка.

Если вы действительно хотите решить этот аспект, следующий класс может оказаться полезным и также проясняет намерение .

public sealed class TriggerField<T>
{
    private T data;

    ///<summary>raised *after* the value changes, (old, new)</summary>
    public event Action<T,T> OnSet;

    public TriggerField() { }

    ///<summary>the initial value does NOT trigger the onSet</summary>
    public TriggerField(T initial) { this.data=initial; }

    public TriggerField(Action<T,T> onSet) { this.OnSet += onSet; }

    ///<summary>the initial value does NOT trigger the onSet</summary>
    public TriggerField(Action<T,T> onSet, T initial) : this(onSet) 
    { 
        this.data=initial;
    }

    public T Value
    {
        get { return this.data;}
        set 
        { 
            var old = this.data;
            this.data = value;
            if (this.OnSet != null)
                this.OnSet(old, value);
        }
    }
}

Позволяет (несколько подробно) использовать это примерно так:

public class Foo
{
    private readonly TriggerField<string> flibble = new TriggerField<string>();
    private int versionCount = 0;

    public Foo()
    {
        flibble.OnSet += (old,current) => this.versionCount++;  
    }

    public string Flibble 
    { 
        get { return this.flibble.Value; }
        set { this.flibble.Value = value; }
    }
}

в качестве альтернативы вы можете выбрать менее подробный вариант, но доступ к Flibble осуществляется не идиоматическим bar.Flibble.Value = "x"; , что было бы проблематично в сценариях рефлексии

public class Bar
{
    public readonly TriggerField<string> Flibble;
    private int versionCount = 0;

    public Bar()
    {
        Flibble = new TriggerField<string>((old,current) => this.versionCount++);
    }
}

  1. или решение, если вы посмотрите на контент сообщества!
0
ответ дан 28 November 2019 в 17:36
поделиться

Для автоматического изменения основных режимов вы можете добавить в свой файл .emacs следующее:

(add-to-list 'auto-mode-alist '("^\\*erl-output\\*$" . my-major-mode))

Это не сработает для вас; это для выбора режима основного , и вам нужен выбор режима второстепенный .

Вместо этого вы можете попробовать Hook . В руководстве говорится:

Хук - это переменная Лиспа, которая содержит список функций, которые должны быть вызваны в каком-то четко определенном случае.

Таким образом, вы должны иметь возможность написать функцию, которая устанавливает второстепенный режим, когда это необходимо. Глядя на Список стандартных хуков , я думаю, вам стоит попробовать temp-buffer-setup-hook или temp-buffer-show-hook .

Вы'

0
ответ дан 28 November 2019 в 17:36
поделиться

Обернуть его в класс? В любом случае, свойство свойства немного похоже на это, связывая данные с методами - "Инкапсуляция", которой они бредили ...

class MyInt
{
    private int n;

    public static implicit operator MyInt(int v) // Set
    {
        MyInt tmp = new MyInt();
        tmp.n = v;
        return tmp;
    }

    public static implicit operator int(MyInt v) // Get
    {
        return v.n;
    }
}

class MyClass
{
    private MyInt myint;

    public void func()
    {
        myint = 5;
        myint.n = 2; // Can't do this.
        myint = myint + 5 * 4; // Works just like an int.
    }
}

Я уверен, что я что-то упускаю? Это кажется слишком нормальным ...

Кстати, мне очень нравится закрытие, безумно.

1
ответ дан 28 November 2019 в 17:36
поделиться

Я не знаю C #, но в Java у вас может быть базовый класс только с частными переменными экземпляра и общедоступными сеттерами и геттерами (должен возвращать копию экземпляра var.) и делать все остальное в унаследованном классе.

«Общим принципом проектирования» было бы «использовать наследование».

2
ответ дан 28 November 2019 в 17:36
поделиться

В C # нет встроенного решения, но я думаю, что ваша проблема может быть решена с помощью хорошего объектно-ориентированного дизайна: У каждого класса должна быть одна цель. Поэтому постарайтесь выделить логику вашего поля в как можно меньший класс. Это уменьшает код, из-за которого вы можете случайно получить доступ к полю. Если вы делаете такие ошибки случайно, ваш класс, вероятно, слишком велик.

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

1
ответ дан 28 November 2019 в 17:36
поделиться

Нет, нет. Мне бы самому это понравилось - что-то вроде:

public string Name
{
    private string name; // Only accessible within the property
    get { return name; /* Extra processing here */ }
    set { name = value; /* Extra processing here */ }
}

Думаю, я впервые предложил это около 5 лет назад в группах новостей C # ... Я не ожидаю, что когда-нибудь это произойдет.

Там есть различные морщины, которые следует учитывать при сериализации и т. д., но я все же думаю, что это было бы хорошо. Я бы предпочел сначала автоматически реализовать свойства только для чтения ...

11
ответ дан 28 November 2019 в 17:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: