Ну, на самом деле они не являются "конструкторами" ни при каком обычном использовании слова "конструктор".
Это выражения, которые можно преобразовать в типы делегатов или типы деревьев выражений - последнее важно при работе с LINQ вне процесса.
Если вы действительно спрашиваете, ожидается ли, что использование двух «эквивалентных» лямбда-выражений может создать неравные экземпляры делегата: да, это так. IIRC, в спецификации языка C # даже говорится, что это так.
Однако, если использовать одно и то же лямбда-выражение более одного раза, всегда не будет создавать различные экземпляры:
using System;
class Test
{
static void Main(string[] args)
{
Action[] actions = new Action[2];
for (int i = 0; i < 2; i++)
{
actions[i] = () => Console.WriteLine("Hello");
}
Console.WriteLine(actions[0] == actions[1]);
}
}
На моем боксе, которые на самом деле печатают True
- actions[0]
и actions[1]
, имеют одинаковое значение - они ссылаются на один и тот же экземпляр. Действительно, мы можем пойти дальше:
using System;
class Test
{
static void Main(string[] args)
{
object x = CreateAction();
object y = CreateAction();
Console.WriteLine(x == y);
}
static Action CreateAction()
{
return () => Console.WriteLine("Hello");
}
}
Опять же, это печатает True
. Это не гарантировано, но здесь компилятор фактически создал статическое поле для кэширования делегата в первый раз, когда это требуется - потому что он не захватывает никакие переменные и т. Д.
В основном это детали реализации компилятора, на которые вы должны не полагаться.