Функциональный делегат без типа возврата


561

Все делегаты Func возвращают значение. Что такое делегаты .NET, которые можно использовать с методами, возвращающими void?

Ответы:


760

Все делегаты Func возвращают что-то; все делегаты Акции возвращают void.

Func<TResult> не принимает аргументов и возвращает TResult:

public delegate TResult Func<TResult>()

Action<T> принимает один аргумент и не возвращает значение:

public delegate void Action<T>(T obj)

Action самый простой «голый» делегат:

public delegate void Action()

Там же Func<TArg1, TResult>и Action<TArg1, TArg2>(и другие до 16 аргументов). Все они (кроме Action<T>) являются новыми для .NET 3.5 (определено в System.Core).


11
К вашему сведению, следующая версия библиотеки базовых классов будет включать в себя типы Func и Action, которые поддерживают более четырех формальных параметров. Я не помню точно, насколько они большие.
Эрик Липперт

88
В .NET 4.0 они теперь идут до 8 параметров. Если они продолжат в том же духе, то в следующей версии он поднимется до одиннадцати !! 11 !!!
Michiel van Oosterhout

9
На самом деле, похоже, что они идут до 16 в 4.0.
Tustin2121

7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... это ясно указывает на то, что компилятор должен иметь возможность справиться с большим количеством аргументов функции, чем он делает это в какой-то момент в будущем !
Крис Морган

6
На самом деле, Tustin2121 прав, они достигли 16 параметров (плюс тип возврата в случае Func<,,, ... ,>) в .NET 4.0, но последние восемь типов каждой «серии» определены в System.Core.dll, а не в mscorlib.dll, так что это будет причиной почему michielvoo не видел их. Однако в версиях 4.5 и 4.5.1 .NET больше не было добавлено ни Funcs, ни Actions. Станет ли эта последовательность A170836 или A170875 ? Следите за обновлениями.
Джеппе Стиг Нильсен


48

Все делегаты Func принимают хотя бы один параметр

Это не правда. Все они принимают по крайней мере один аргумент типа, но этот аргумент определяет тип возвращаемого значения.

Так что не Func<T>принимает параметров и возвращает значение. Используйте Actionили Action<T>когда вы не хотите возвращать значение.


27

Попробуй System.Func<T>иSystem.Action


1
Я не думаю, что 0 аргументов и тому подобное существуют в .Net 2.0.
Брайан

1
Это странно: Func вообще не существует в .Net 2.0, хотя есть Predicate и Action.
Джоэл Коухорн

2
Для .NET 2.0 используйте делегат MethodInvoker.
Тревор Эллиотт

.NET 2 также имел (или имеет) тип делегата, Converter<TInput, TOutput>который был похож на более поздний Func<T, TResult>. Он использовался в List<>.ConvertAllметоде, который проецировал каждый элемент в a List<>на другой объект и помещал все «значения функции» в новый List<>. (Позже для этого часто использовали бы Linq Select.)
Джепп Стиг Нильсен,

0

Иногда вам может понадобиться написать делегат для обработки событий, и в этом случае вы можете воспользоваться тем, System.EvenHandler<T>что неявно принимает аргумент типа objectв дополнение ко второму параметру, который должен быть производным EventArgs. EventHandlers вернетсяvoid

Я лично нашел это полезным во время тестирования для создания одноразового обратного вызова в теле функции.


0

... не принимает аргументов и имеет возвращаемый тип void?

Если вы пишете для System.Windows.Forms, вы также можете использовать:

public delegate void MethodInvoker()

0

Очень простой способ вызвать функции возврата и возврата. использует Func и Action соответственно. (см. также https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Попробуйте этот пример

using System;

public class Program
{
    private Func<string,string> FunctionPTR = null;  
    private Func<string,string, string> FunctionPTR1 = null;  
    private Action<object> ProcedurePTR = null; 



    private string Display(string message)  
    {  
        Console.WriteLine(message);  
        return null;  
    }  

    private string Display(string message1,string message2)  
    {  
        Console.WriteLine(message1);  
        Console.WriteLine(message2);  
        return null;  
    }  

    public void ObjectProcess(object param)
    {
        if (param == null)
        {
            throw new ArgumentNullException("Parameter is null or missing");
        }
        else 
        {
            Console.WriteLine("Object is valid");
        }
    }


    public void Main(string[] args)  
    {  
        FunctionPTR = Display;  
        FunctionPTR1= Display;  
        ProcedurePTR = ObjectProcess;
        FunctionPTR("Welcome to function pointer sample.");  
        FunctionPTR1("Welcome","This is function pointer sample");   
        ProcedurePTR(new object());
    }  
}

1
Спасибо за этот фрагмент кода, который может оказать некоторую ограниченную, немедленную помощь. Надлежащее объяснение было бы значительно улучшить свою долгосрочную ценность , показывая , почему это хорошее решение проблемы, и сделает его более полезным для читателей будущих с другими подобными вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
iBug
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.