Patrick Skelton Ответов: 1

Могу ли я привести действие<T> к действию?


Ладно, я должен поднять руки и признать, что виновен в копировании кода (в спешке), не понимая его.

Код, который я скопировал, был предназначен для реализации System.Windows.Input.ICommand интерфейс. Я не могу найти источник кода, который скопировал, но, просматривая его сейчас, я решил, что он выглядит странно для меня.

Вот код, который меня беспокоит.

public class Command : ICommand
{
    public Command( Action<object> execute )
    {
        _execute = execute;
    }

	public Command( Action execute ) : this( (Action<object>)( o => execute() ) )
	{
	}

	private readonly Action<object> _execute = null;
}


Похоже, что он выполняет цепочку конструкторов для хранения параметра типа Action в переменной типа Action<object> Он компилируется, и следующие тесты, похоже, показывают, что он работает нормально:

[TestClass]
public class UTSupportCommand
{
    [TestMethod]
    public void Command_with_Action_parameter_executes()
    {
        Command command = new Command( ActionWithObjectParameter );
        command.Execute( "A" );
        Assert.IsTrue( _t1 == "A" );
    }

    [TestMethod]
    public void Command_with_no_parameter_executes()
    {
        Command command = new Command( ActionWithNoParameter );
        command.Execute( "X" );
        Assert.IsTrue( _t2 == "B" );
    }

    private void ActionWithObjectParameter( object s )
    {
        _t1 = (string)s;
    }

    private void ActionWithNoParameter()
    {
        _t2 = "B";
    }

    private string _t1 = "Z";
    private string _t2 = "Z";
}


Что действительно озадачивает меня, так это то, как я могу передать параметр в Action это не требует никаких параметров. Что с ним происходит?

Я был бы признателен за любые комментарии о том, есть ли что-то не так с этим кодом и что именно он делает.

Добрые пожелания ~ Патрик

Что я уже пробовал:

Я попробовал тесты, показанные выше, которые, кажется, работают нормально.

1 Ответов

Рейтинг:
8

Nathan Minier

Это просто прекрасно, потому что вы на самом деле оборачиваете неродовое действие (не принимает никаких параметров) с действием<t>.

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

public bool DoSomething(int useless)
{
   return true;
}


Теперь конструктор команд работает так, как вы подразумевали: если он получает не универсальное действие, то он обернет его в действие "объект". Обернутая команда ничего не делает с аргументом объекта, точно так же, как приведенный выше пример ничего не делает с ним, но теперь она будет выполняться и соответствовать ожидаемой сигнатуре.