Подтвердить что ты не робот

Является ли это изменением, изменяющим модификатор доступа публичного имущества?

Если я изменю модификатор доступа сеттера публичного свойства от частного к публичному, это вызывает какое-либо нарушение в других сборках, которые ссылаются на него?

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога в январе 2012 года. Спасибо за отличный вопрос!


Я предполагаю, что под "прерыванием изменений" вы подразумеваете "когда я перекомпилирую код, который зависел от этой сборки, все еще компилируется ли код, который использовался для компиляции?"

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

// Assembly Alpha
public class Charlie
{
    public int P { get; private set; }
}
public class Delta
{
    public int P { get; set; }
}

А затем в другой сборке, которая ссылается на Альфа:

// Assembly Echo
class Foxtrot
{
    static void M(Action<Charlie> f) {}
    static void M(Action<Delta> f) {}
    static void Golf()
    {
        M(y=>{y.P = 123;});
    }
}

Вы компилируете сборку Echo. Класс Foxtrot имеет метод Golf, который разрешает перегрузки для M. M имеет две перегрузки; тот, который действует на Чарли, и тот, который действует на Дельту. Если лямбда-параметр y имеет тип Чарли, то лямбда-тело выдает ошибку доступности, и, следовательно, эта перегрузка M не является подходящим кандидатом. Разрешение перегрузки выбирает вторую перегрузку, и компиляция завершается успешно.

Теперь вы измените сборку Alpha так, чтобы сеттер Charlie.P был общедоступным. Вы перекомпилируете Echo. Теперь вы получаете ошибку разрешения перегрузки, потому что обе перегрузки M одинаково действительны, и ни одна не лучше, чем другая. Компиляция Echo не удалась из-за изменения в Alpha. Ваше изменение в Альфе было серьезным изменением.

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

Ответ 2

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

Некоторые языки не позволяют переопределить свойство без переопределения всех видимых аксессуаров. VB - такой язык.

Скажем, у вас есть следующий класс С#:

namespace TestLibrary
    public class A {
        public virtual int X { 
            get { return 0; } 
            private set { Console.WriteLine("A.set_X called."); } 
        }
    }
}

В проекте VB, который ссылается на вашу библиотеку, вы имеете определение класса:

Class B : Inherits TestLibrary.A
    Public Overrides ReadOnly Property X As Integer
        Get
            Return MyBase.X
        End Get
    End Property
End Class

Обратите внимание на модификатор ReadOnly в свойстве. Это требуется в VB, потому что вы определяете только получателя. Если вы оставите это, вы получите ошибку времени компиляции:

Свойство без спецификатора ReadOnly или WriteOnly должно обеспечивать как "Get", так и "Set".

Теперь удалите модификатор private из установщика в вашем классе С#:

namespace TestLibrary
    public class A {
        public virtual int X { 
            get { return 0; } 
            set { Console.WriteLine("A.set_X called."); } 
        }
    }
}

Теперь вы получите ошибку времени компиляции в коде VB:

'Открытый переопределяет свойство ReadOnly X As Integer' не может переопределить "Общедоступное переопределяемое свойство X как целое", поскольку они отличаются "ReadOnly" или "WriteOnly".

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

Ответ 3

Это зависит от того, насколько строго вы хотите быть "нарушением изменений".

Одно определение: нарушает ли сборка или выполнение ссылочного кода.

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

По первому определению это не является нарушением изменений. По второму определению это нарушение.

Ответ 4

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

Но ранний код не сломается.

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

Ответ 5

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

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

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

Ответ 6

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