Существуют ли какие-либо официальные способы написания выражения, вызванного немедленным вызовом?
Что-то вроде этого:
var myObject = new MyClass()
{
x = " ".Select(y =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
})
};
Я понимаю, что Select не предназначен для использования таким образом. Но да, какие еще способы сделать то же самое?
Ответы
Ответ 1
Я удивлен, что никто не упомянул об этом, но вы можете использовать класс Lazy<T>
:
var myObject = new MyClass()
{
x = new Lazy<string>(() =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
}).Value // <-- Evaluate the function here
};
В качестве альтернативы, если вы хотите не указывать тип возвращаемого значения в любом месте (как вы это делаете с new Lazy<string>
, потому что конструкторы не поддерживают вывод типа), вы можете реализовать простой общий метод, подобный этому:
public static T Eval<T>(Func<T> func)
{
return func();
}
И тогда вы можете позвонить следующим образом:
var myObject = new MyClass()
{
x = Eval(() =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
})
};
Обновление: С# 7 вводит локальные функции. На самом деле это не IFFE, но они могут решить множество связанных вопросов. Например:
var myObject = new MyClass()
{
x = GetX()
};
string GetX() {
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
}
Ключевым моментом здесь является то, что GetX
может быть объявлен в рамках того же метода, что и myObject
, используя тот же объем, что и он.
Ответ 2
Для реального кода сделать его функцией... Для развлекательных целей эквивалент С# JavaScript IIFE более прямой, чем Select
:
var myObject = new MyClass()
{
x =((Func<int>)(() => {return 2;}))(),...
Ответ 3
Хотя, конечно, не "официальный", вы можете использовать необязательные именованные параметры в конструкторе или отдельный метод factory/builder:
public class MyClass
{
public string x { get; private set; }
public MyClass(Func<string> x = null)
{
if (x != null)
this.x = x();
}
}
с использованием:
var myClass = new MyClass(
x: () =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
}
);
Console.WriteLine(myClass.x); //"I'm a bitter old man"
Итак, это не точный синтаксис, который вы запрашивали, но довольно близко и пропускает странность LINQ.
Тем не менее, мне это не нравится. Просто предлагая это как пищу для размышлений.:)
EDIT: Я решил, что добавлю стиль метода factory, поскольку это правдоподобно, что вы используете это в классе, который вы не можете (или не хотите) изменить его конструктор:
public static class MyFactory
{
public static MyClass CreateMyClass(Func<string> x = null)
{
var myClass = new MyClass()
if (x != null)
myClass.x = x();
return myClass;
}
}
С аналогичным использованием (просто вызывая метод factory):
var myClass = MyFactory.CreateMyClass(
x: () =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
}
);
РЕДАКТОР: И эй, пока мы на нем. Почему бы не уйти с глубокого конца и сделать это с помощью отдельного строителя и оскорбить неявных операторов!
public class MyClassBuilder
{
public Func<string> x { get; set; }
public static implicit operator MyClass(MyClassBuilder builder)
{
var myClass = new MyClass();
if (builder.x != null)
myClass.x = builder.x();
return myClass;
}
}
С использованием, например:
MyClass myClass = new MyClassBuilder
{
x = () =>
{
//Do stuff..
if (2 + 2 == 5)
return "I like cookies";
else if (2 + 2 == 3)
return "I like muffins";
//More conditions...
else
return "I'm a bitter old man";
}
};
Итак, теперь синтаксис идентичен, за исключением того, что вы должны явно вводить свой экземпляр вместо использования var
.
Ответ 4
Вот что наш коллега придумал:
var myObject = new {
x = new Func<int>(() => {return 2;})()
};
Обратите внимание, что это основано на ответе Алексея.