Как обеспечить работоспособность конструкций типа Ship.Attack().Ship;?

Как обеспечить работоспособность конструкций типа Ship.Attack().Ship; вместо Ship.Attack(Ship); где вместо класса Ship объекты этого класса, а функция Attack() реализует изменения второго объекта перемеными первого: _hp второго объекта уменьшаются на _force первого в одной функции или двух перегруженных одноимённых функций. Зачем это? Хочу, мне безумно нравится сахарность такой конструкции. В чём проблема? Как передать функции переменую второго объекта Attack().Ship да ещё с возможностью изменить приватную переменную (т.е. должна сработать одномённая функция у второго объекта).


Ответы (2 шт):

Автор решения: Blackmeser

Синтаксис языка такого не позволит.

→ Ссылка
Автор решения: aepot

Конкретно то что вы хотите сделать, невозможно. Потому что после точки указывается только член класса. Туда нельзя синтаксически засунуть локальную переменную.

Но не в одной атаке же смысл.

Предлагаю немного другое.

ship1.Target(ship2).Attack();

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

ship1.Target(ship2).Follow(); // следовать за целью
ship1.Target(ship2).Avoid(); // убегать от цели

Далее там можно стрелять из ГК, пускать торпеды, на что фантазии хватит. А реализуется такое достаточно просто.

public class Ship
{
    public Ship CapturedTarget { get; private set; }

    public Ship Target(Ship target)
    {
        CapturedTarget = target;
        return this;
    }

    public Ship Attack()
    {
        if (CapturedTarget is null)
            throw new NullReferenceException($"{nameof(CapturedTarget)} was null");

        // ... атаковать цель

        return this;
    }
}

Возврат значением из метода текущего класса позволяет ставить точки бесконечно. Это называется Fluent Interface. На эту тему много всякого понаписано, поищите, почитайте. Скорее всего понимание того, как строяться Fluent интерфейсы, вам и позволит понять, что можно сделать, а что нельзя.

ship1.Target(ship2).Follow().Target(ship3).Attack().Avoid();
→ Ссылка