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

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

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


I. Контроль простых параметров

1. Передача параметров значимого типа

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

2. Передача параметров ссылочного типа

a. Структуры данных, состоящие из типов значений

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

b. Структуры данных, содержащие поля ссылочного типа

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

public class SuperClass
{
    private readonly int  _no;
    private readonly SubClass _tag;

    public int NO
    {
        get{ return _no;}
    }

    public SubClass Tag
    {
        get{ retirn _tag;}
    }

    public SuperClass(int no,SubClass tag)
    {
        _no=no;
        _tag=tag;   
    }
}


public class SubClass
{
    private readonly int _field;

    public int Field
    {
        get{ return _field;}
    }

    public SubClass(int field)
    {
        _field=field;
    }
}

II. Контроль передачи сложных параметров ссылочного типа

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

1. Параметры-коллекции (то же касается параметров ссылочного типа, содержащих поля коллекций)

Для версий до .NET 4.5 можно использовать интерфейсы, не содержащие методов изменения элементов коллекции, вместо конкретных типов коллекций. Например, используйте IEnumerableинтерфейс вместо List.NET 4.5 может напрямую использовать интерфейс IReadOnlyCollection или типы коллекций, реализующие этот интерфейс.

2. Параметры массива

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


III. Чтобы понять вышесказанное, необходимо чётко различать различия между следующими понятиями

  • 1. Разница между типами значений и ссылочными типами
  • 2. Разница между передачей по значению и передачей по ссылке (ref и out)
  • 3. Разница между передачей параметров ссылочного типа и передачей параметров ссылочного типа по ссылке (ref и out) [Этот момент вызывает наибольшую путаницу]

Разница в том, что когда во время использования параметра для ссылки создаётся новый объект, первый случай не влияет на исходное значение, а второй влияет на исходное значение. Пример:

void FunA(MyClass a)
{
     a=new MyClass("A");
}

void FunB(ref MyClass a)
{
    a=new MyClass("B");
}

 

void Test()
{
    MyClass a=new MyClass("A"); 
    FunA(a);
    Print(a);              //a还是原始的对象 TEST
    FunB(ref a);
    Print(a);               //a变为新对象   B
}

Запомните один принцип:Типы значений передают копию значения, ссылочные типы передают ссылку на объект. Поэтому изменения параметров-значений не влияют на исходное значение, а изменения ссылочных типов влияют на исходное значение; создание параметра, переданного по значению, не влияет на исходное значение, а передача по ссылке (ref и out) влияет на исходное значение.

Исходный адрес: https://www.cnblogs.com/from1991/p/5335585.html