2013-02-14 2 views
2

У меня есть некоторые словарные объекты, которые не меняются во время работы приложения. Я планирую использовать статические переменные readonly, может ли кто-либо предоставить входные данные для ниже точек.Статическая инициализация переменных readonly

  1. Разница между инициализацией непосредственно как статического ReadOnly свойства и статические свойствами с оператором GET подкрепленной частными статическими переменными только для чтения.

  2. Есть ли риск использовать их, поскольку я читал онлайн, чтобы не использовать public static переменных. Это относится к этой ситуации.

ответ

3

У меня есть некоторые словарные объекты, которые не меняются во время работы приложения.

Когда вы помечаете переменную типа словаря readonly, вы запрещаете замену словаря, который вы назначаете другим словарем. Вы делаете , а не, чтобы сделать этот словарь доступным только для чтения, в том смысле, что, как только вызывающий абонент получит доступ к этому словарю, он может свободно меняться любым способом, который он хочет, очищая его или устанавливая неверные значения (по ошибка, без сомнения). Если вам нужно сделать словарь только для чтения, подумайте о заимствовании реализации обертки только для чтения from this answer.

В общем, единственное преимущество добавления свойства на вершине переменной, или имеющие {get;private set;} автоматическое свойство, над readonly static ваша способность выполнять дополнительные проверки в инкубаторе, или добавить некоторый код в добытчика (скажем, , для сбора статистики доступа или для ведения журнала). Имеются также последствия для доступа к полю посредством отражения. Это не похоже на то, что вы делаете что-либо из этого, поэтому подвергая переменную readonly звучит правильно и не представляет дополнительных рисков.

EDIT: (на использование отражения) При доступе к данным объекта посредством отражения, необходимо указать, если вы доступ к свойству Xyz или поле Xyz. Напротив, когда вы пишете программу на C#, вы пишете SomeClass.Xyz, а компилятор выясняет, является ли это свойством или полем для вас. Если вы создадите класс, который предоставляет поле Xyz, а затем решите заменить его свойством Xyz, перекомпиляция кода, который ссылается на Xyz, напрямую - это все, что требуется. Однако, если вы написали код, который обращается к Xyz с помощью API отражения, этот код нужно будет переписать, потому что компилятор не сможет поймать изменение для вас.

+0

Это помогло! Я не понимал здесь размышлений, о котором также упомянул Одед. Хотя я не могу его использовать, не могли бы вы предоставить дополнительную информацию. – Sunny

+0

@Sundeep Я отредактировал ответ, чтобы развернуть последствия отражения. – dasblinkenlight

1

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

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

1

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

1

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

// access between these two is almost identical 
public class Foo 
{ 
    public readonly static IDictionary<string, int> bar = 
     new Dictionary<string, int>(); 
    public static IDictionary<string, int> Bar 
    { 
     get { return bar; } 
    } 
} 

вопрос вы собираетесь работать, состоит в том, что даже если поле было помечено как readonly это все еще изменчивый. Что нужно, чтобы кто-то не позвонил Foo.Bar.Clear(); Чтобы решить эту проблему, вы можете создать копию и вернуть ее, или вы можете найти использование словаря для чтения.

public class Foo 
{ 
    private readonly static IDictionary<string, int> bar = 
     new Dictionary<string, int>(); 
    public static IDictionary<string, int> Bar 
    { 
     // now any calls like Foo.Bar.Clear(); will not clear Foo.bar 
     get { return new Dictionary<string, int>(bar); } 
    } 
} 

Тогда, если вам, если вам нужно добавить или удалить элементы из Foo.Bar вы можете создавать функции, чтобы ограничить как модифицирован основной объект.

public static void AddItem(string key, int value) 
{ } 
public static void RemoveItem(string key) 
{ } 

Даже если вы используете ReadonlyDictionary реализацию, вы все равно можете столкнуться с проблемами, с модификацией, если TKey или TValue словаря изменчивы.

В целом те причины, которые вы видели, чтобы избежать статических переменных, остаются в силе здесь. Вы вводите статическую зависимость, которая будет перетаскиваться, когда код, который использует Foo.Bar, используется повторно. Если объект, к которому вы статически обращаетесь, неизменен, а также только для чтения, существует ряд непредвиденных побочных эффектов, которые могут возникнуть.

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

public void CompRoot() 
{ 
    var bar = new ReadonlyDictionary(
     ... initialize with desired values ... 
      // also this object is not in .NET but there 
      // are many available on the net 
    ); 

    var obj = new UsesBarDependency(bar); 
} 

public class UsesBarDependency 
{ 
    private readonly ReadonlyDictionary bar; 

    public UsesBarDependency(ReadonlyDictionary bar) 
    { 
      if (bar == null) 
       throw new ArgumentNullException("bar"); 
      this.bar = bar; 
    } 

    public void Func() 
    { 
     // use to access the dependency 
     this.bar 
     // over 
     Foo.Bar 
    } 
} 

Это позволяет пользователям UsesBarDependency обеспечить любые ReadonlyDictionary к объекту вместо того, чтобы быть вынуждены использовать статическую Foo.Bar зависимость.

Смежные вопросы