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

Является ли плохой практикой передавать "this" в качестве аргумента?

В настоящее время я соблазнился написать следующее:

public class Class1() 
{
    public Class1() 
    {
        MyProperty = new Class2(this);
    }

    public Class2 MyProperty { get; private set; }
}

public class Class2() 
{
    public Class2(Class1 class1) 
    {
        ParentClass1 = class1;
    }

    public Class1 ParentClass1 { get; set; }
}

Передача "this" в качестве аргумента признака проблемы проектирования? Что было бы лучше?

4b9b3361

Ответ 1

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

Ответ 2

нет, это не проблема. Именно поэтому существует 'this' ключевое слово, чтобы вы могли обойти

Ответ 3

Трудно сказать, что вы опубликовали. Вопрос, который вы должны задать себе: почему класс 2 должен знать о классе1? Какие типы операций выполняет класс 2 для класса 1 в течение его жизни, и есть ли лучший способ реализовать это отношение?

Имеются веские причины для этого, но это зависит от фактических классов.

Ответ 4

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

Ответ 5

Просто для облегчения вашего ума:

Передача this в качестве параметра выполняется даже классами внутри BCL. Например, тип List<T>.Enumerator содержит ссылку на его родительский объект List<T>, чтобы знать, был ли список изменен между перечислениями (и, следовательно, когда нужно было выбросить InvalidOperationException).

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

Ответ 6

Чтобы привести пример, проверьте шаблон посетителя:

interface IVisitor {
 Visit(SomeClass c);
 Visit(AnotherClass c);
}

interface IAcceptVisitor {
  void Accept(IVisitor v);
}

public SomeClass : IAcceptVisitor {
  void Accept(IVisitor v) {
    v.Visit(this);
  }
}

Ответ 7

Я не знаю модель памяти в С# подробно (вообще). Но передача этого из конструктора в другой объект по своей сути является небезопасной на многих языках (включая Java).

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

В вашем примере такого использования undefined не происходит, но как бы вы гарантировали, что этого не будет в будущем? Что делать, если кто-то подклассы/изменяет Class2 таким образом, что он использует что-то из ParentClass1 в своем собственном конструкторе?

Ответ 8

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

Я особенно использовал его при пересечении деревьев в реализациях компилятора или в инструментах GUI.