У меня есть класс, который принимает действие для конструктора, скажем, класс A.

public class A
{
    public A(Action action) {...}
}

И я создаю его.

class Program
{
    void Main()
    {
        A a = new A(() => { DoSomethingWith(x); });
    }
}

Возникает вопрос: как я могу ссылаться на «а» в моем действии? Другими словами, как я могу заменить «x» на «a»?
Я пробовал ключевое слово this, но оно относится к программе.
Кстати, я не могу использовать другие входные данные для своего конструктора, потому что в этом проекте действия очень случайны.

-1
Bamdad 13 Мар 2018 в 03:55

2 ответа

Лучший ответ

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

public class A
{
    public A(Action<A> myAction)
    {
        myAction(this);
    }
}

public class B
{
    public B()
    {
        var myA = new A((a) => { DoSomethingWithA(a); });
    }

    public void DoSomethingWithA(A a)
    {

    }
}

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

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

1
Ron Beyer 13 Мар 2018 в 01:28

Как уже указывалось, вы не можете назначить действие в конструкторе, потому что a еще не создан. Не путайте назначение действия с его запуском . Вероятно, вы захотите запустить действие в другое время, чем при создании a.

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

public class A
{
    Action<A> MyAction
    public A(Action<A> action) 
    {
        MyAction = action;
    }
    public void DoMyAction() 
    {
        MyAction(this);
    }
}

class Program
{
    void Main()
    {
        var a = new A((x) => { DoSomethingWith(x); });
        a.DoMyAction();
    }
}
0
see sharper 13 Мар 2018 в 01:55