Разработка полей

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

Не следует предоставлять публичные или защищенные поля экземпляра.

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

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

Например, класс Math определяет E и PI как статические константы.

Компилятор вставляет код инициализации полей const непосредственно в код вызова; это означает, что значения const никогда не будут изменены и не возникнет проблем совместимости.

Для предварительно определенных экземпляров объекта следует использовать публичные статические поля, доступные только для чтения.

Например, класс DateTime обеспечивает статические поля, доступные только для чтения, которые можно использовать для получения объектов DateTime, которые установлены в максимальное или минимальное значение времени. См. разделы MaxValue и MinValue.

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

Объекты, созданные с использованием изменяющегося типа, можно модифицировать после их создания. Например, массивы и большинство коллекций являются изменяющимися типами, в то время как Int32, Uri и String являются неизменяющимися типами. Для полей, содержащих изменяющийся ссылочный тип, модификатор "read-only" предотвращает перезапись значения поля, но не защищает изменяющийся тип от модификации.

Следующий пример кода демонстрирует проблему, возникающую при использовании полей с модификатором "read-only". Класс BadDesign создает поле с модификатором "read-only" и предоставляет его только для чтения. Это не предотвращает модификацию содержимого поля с модификатором "read-only" в классе ShowBadDesign.

Imports System

Namespace Examples.DesignGuidelines.Fields

    Public Class BadDesign

        Public Readonly dataValues as Integer() = {1,2,3}

        Public ReadOnly Property Data as Integer ()

            Get 
                Return dataValues
            End Get
        End Property

        Public Sub WriteData()

            For Each i as Integer In dataValues

                Console.Write ("{0} ", i)
            Next i
            Console.WriteLine()
        End Sub
    End Class

    Public Class ShowBadDesign

        Public Shared Sub Main()

            Dim bad as BadDesign = new BadDesign()
            ' The following line will write: 1 2 3
            bad.WriteData()

            Dim badData as Integer() = bad.Data
            For i as Integer  = 0 To badData.Length -1

                badData(i) = 0
            Next i

            ' The following line will write: 0 0 0
            ' because bad's data has been modified.
            bad.WriteData()
        End Sub
    End Class
End Namespace
using System;

namespace Examples.DesignGuidelines.Fields
{
    public class BadDesign
    {
        public readonly int[] data = {1,2,3};

        public int [] Data
        {
            get {return data;}
        }
        public void WriteData()
        {
            foreach (int i in data)
            {
                Console.Write ("{0} ", i);
            }
            Console.WriteLine();
        }
    }
    public class ShowBadDesign
    {
        public static void Main()
        {
            BadDesign bad = new BadDesign();
            // The following line will write: 1 2 3
            bad.WriteData();

            int[] badData = bad.Data;
            for (int i = 0; i< badData.Length; i++)
            {
                badData[i] = 0;
            }
            // The following line will write: 0 0 0
            // because bad's data has been modified.
            bad.WriteData();
        }
    }
}
using namespace System;

namespace Examples { namespace DesignGuidelines { namespace Fields
{
    public ref class BadDesign
    {
    public:
        static const array<int>^ data = {1,2,3};

        property array<int>^ Data
        {
            array<int>^ get() {return data;}
        }

        void WriteData()
        {
            for each (int i in data)
            {
                Console::Write ("{0} ", i);
            }
            Console::WriteLine();
        }
    };

    public ref class ShowBadDesign
    {
    public:
        static void Main()
        {
            BadDesign^ bad = gcnew BadDesign();
            // The following line will write: 1 2 3
            bad->WriteData();

            array<int>^ badData = bad->Data;
            for (int i = 0; i< badData->Length; i++)
            {
                badData[i] = 0;
            }
            // The following line will write: 0 0 0
            // because bad's data has been modified.
            bad->WriteData();
        }
    };
}}}

Охраняется авторским правом Copyright 2005 Microsoft Corporation. Все права защищены.

Фрагменты — © Addison-Wesley Corporation. Все права защищены.

Для дополнительной информации о разработке руководящих принципов, смотрите "руководства по разработке рамок: Конвенций, идиомы и шаблоны для повторного использования.NET библиотек"книга, Кшиштоф Cwalina и Брэд Абрамс, опубликованных Addison-Wesley, 2005 года.

См. также

Другие ресурсы

Правила разработки членов

Руководство по разработке библиотек классов