Почему C# не предоставляет стилю C++ 'друга' ключевое слово? [закрытый]

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

205
задан Community 23 May 2017 в 01:47
поделиться

11 ответов

Наличие друзей в программировании более или менее считают "грязным" и легким злоупотребить. Это повреждает отношения между классами и подрывает некоторые фундаментальные атрибуты языка OO.

Однако это - хорошая функция, и я использовал его много времен сам в C++; и хотел бы использовать его в C# также. Но я держал пари из-за "чистого" OOness C# (по сравнению с псевдо OOness C++), MS решил что, потому что Java не имеет никакого друга ключевое слово, C# не был должен ни один (просто ребячество;))

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

РЕДАКТИРОВАНИЕ Позволило мне разъяснить, как друг ключевое слово подрывает ООП.

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

64
ответ дан AustinWBryan 23 November 2019 в 04:52
поделиться

Необходимо быть в состоянии выполнить те же виды вещей, что "друг" используется для в C++ при помощи интерфейсов в C#. Это требует, чтобы Вы явно определили, какие участники передаются между этими двумя классами, который является дополнительной работой, но может также сделать код легче понять.

, Если у кого-то есть пример разумного использования "друга", который не может быть моделирован с помощью интерфейсов, совместно используйте его! Я хотел бы лучше понять различия между C++ и C#.

13
ответ дан Parappa 23 November 2019 в 04:52
поделиться

Для получения информации другая related-but-not-quite-the-same вещь в.NET [InternalsVisibleTo], который позволяет блоку определять другой блок (такой как блок модульного теста), который (эффективно) имеет "внутренний" доступ к типам/участникам в исходном блоке.

48
ответ дан Marc Gravell 23 November 2019 в 04:52
поделиться

На ноте стороны. Используя друга не о нарушении инкапсуляции, но наоборот это об осуществлении его. Как accessors+mutators, перегрузка операторов, общедоступное наследование, downcasting, и т.д. , это часто неправильно используется, но это не означает, что ключевое слово имеет не, или хуже, плохая цель.

Видят Konrad Rudolph сообщение в другом потоке, или если Вы предпочитаете, см. соответствующая запись в FAQ C++.

100
ответ дан Community 23 November 2019 в 04:52
поделиться

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

0
ответ дан bashmohandes 23 November 2019 в 04:52
поделиться

Я подозреваю, что это имеет некоторое отношение к модели компиляции C# - создающий IL JIT, компилирующий это во времени выполнения. т.е.: та же причина, что дженерики C# существенно отличаются от дженериков C++.

1
ответ дан Stewart Johnson 23 November 2019 в 04:52
поделиться

Это - на самом деле не проблема с C#. Это - фундаментальное ограничение в IL. C# ограничен этим, как любой другой.Net язык, который стремится поддаваться проверке. Это ограничение также включает управляемые классы, определенные в C++ / CLI ( раздел Spec 20.5 ).

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

7
ответ дан JaredPar 23 November 2019 в 04:52
поделиться

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

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

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

8
ответ дан Andy Dent 23 November 2019 в 04:52
поделиться

Можно быть рядом с C++ "друг" с ключевым словом C#, "внутренним" .

8
ответ дан jeffm 23 November 2019 в 04:52
поделиться

В C # отсутствует ключевое слово "friend" по той же причине, по которой отсутствует детерминированное уничтожение. Изменение условностей заставляет людей чувствовать себя умными, как будто их новые пути лучше чужих старых. Все дело в гордости.

Сказать, что «классы друзей - это плохо», так же недальновидно, как и другие неквалифицированные утверждения, такие как «не используйте gotos» или «Linux лучше, чем Windows».

Ключевое слово "friend" в сочетании с прокси-классом - отличный способ предоставить только определенные части класса конкретному другому классу (классам). Прокси-класс может выступать в качестве надежного барьера против всех других классов. «public» не допускает такой таргетинга, а использование «protected» для получения эффекта с наследованием неудобно, если действительно нет концептуальных отношений «есть».

8
ответ дан 23 November 2019 в 04:52
поделиться

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

1
ответ дан 23 November 2019 в 04:52
поделиться
Другие вопросы по тегам:

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