Сначала я хочу исправить Грега: function abc(){}
тоже облагается & mdash; имя abc
определяется в области, где это определение встречается. Пример:
function xyz(){
function abc(){};
// abc is defined here...
}
// ...but not here
Во-вторых, можно комбинировать оба стиля:
var xyz = function abc(){};
xyz
будет определяться как обычно, abc
не определено во всех браузеров, но Internet & nbsp; Explorer & mdash; не полагайтесь на его определение. Но он будет определен внутри своего тела:
var xyz = function abc(){
// xyz is visible here
// abc is visible here
}
// xyz is visible here
// abc is undefined here
Если вы хотите выполнять функции псевдонима во всех браузерах, используйте этот вид объявления:
function abc(){};
var xyz = abc;
. В этом случае оба xyz
и abc
- это псевдонимы одного и того же объекта:
console.log(xyz === abc); // prints "true"
. Одной из основополагающих причин использования комбинированного стиля является атрибут «name» объектов функций (не поддерживаемый Internet & nbsp; Explorer). В основном, когда вы определяете функцию типа
function abc(){};
console.log(abc.name); // prints "abc"
, ее имя автоматически назначается. Но когда вы определяете его как
var abc = function(){};
console.log(abc.name); // prints ""
, его имя пуст & mdash; мы создали анонимную функцию и присвоили ей некоторую переменную.
Еще одна веская причина использовать комбинированный стиль - использовать короткое внутреннее имя для ссылки на себя, предоставляя длинное неконфликтное имя для внешних пользователей :
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
// Let it call itself recursively:
shortcut(n - 1);
// ...
// Let it pass itself as a callback:
someFunction(shortcut);
// ...
}
В приведенном выше примере мы можем сделать то же самое с внешним именем, но оно будет слишком громоздким (и медленнее).
(Другой способ ссылаться на себя - это использовать arguments.callee
, который все еще относительно длинный и не поддерживается в строгом режиме.)
Вниз, JavaScript обрабатывает оба утверждения по-разному. Это объявление функции:
function abc(){}
abc
здесь определено везде в текущей области:
// We can call it here
abc(); // Works
// Yet, it is defined down there.
function abc(){}
// We can call it again
abc(); // Works
Кроме того, он поднялся с помощью инструкции return
:
// We can call it here
abc(); // Works
return;
function abc(){}
Это выражение функции:
var xyz = function(){};
xyz
здесь определено из точки назначения:
// We can't call it here
xyz(); // UNDEFINED!!!
// Now it is defined
xyz = function(){}
// We can call it here
xyz(); // works
Объявление функции vs выражение функции является реальной причиной того, что существует разница, продемонстрированная Грегом.
Забавный факт:
var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"
Лично я предпочитаю декларацию «выражение функции», потому что таким образом я может контролировать видимость. Когда я определяю функцию, подобную
var abc = function(){};
, я знаю, что я определил функцию локально. Когда я определяю функцию, подобную
abc = function(){};
, я знаю, что я определил ее глобально, указав, что я не определял abc
где-либо в цепочке областей. Этот стиль определения устойчив даже при использовании внутри eval()
. Хотя определение
function abc(){};
зависит от контекста и может оставить вас гадать, где оно фактически определено, особенно в случае eval()
& mdash; ответ: это зависит от браузера.
Сообщение об ошибке в точности: метод Main()
не может быть async
, потому что, когда возвращается Main()
, приложение обычно заканчивается.
Если вы хотите создать консольное приложение, которое использует async
, простым решением является создание async
версии Main()
и синхронно Wait()
по отношению к реальному Main()
:
static void Main()
{
MainAsync().Wait();
}
static async Task MainAsync()
{
// your async code here
}
Это один из редких случаев где смешение await
и Wait()
является хорошей идеей, вы обычно не должны этого делать.
Обновление: Async Main поддерживается в C # 7.1 .
Оберните свой асинхронный код в MainAsync()
- который является асинхронной функцией, затем вызовите MainAsync().GetAwaiter().GetResult();
Разница между кодом в примере ссылки и вашим заключается в том, что вы пытаетесь пометить метод Main()
с помощью модификатора async
- это недопустимо, и ошибка говорит о том, что именно - Main()
- это «точка входа» в приложение (это метод, который запускается при запуске вашего приложения), и ему не разрешено быть async
.
Начиная с C # 7.1 существует 4 новых подписи для метода Main
, которые позволяют сделать это async
( Источник , Источник 2 , Источник 3 ):
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
Вы можете пометить свой метод Main
ключевым словом async
и использовать await
внутри Main
:
static async Task Main(string[] args)
{
Task<string> getWebPageTask = GetWebPageAsync("http://msdn.microsoft.com");
Debug.WriteLine("In startButton_Click before await");
string webText = await getWebPageTask;
Debug.WriteLine("Characters received: " + webText.Length.ToString());
}
C # 7.1 доступен в Visual Studio 2017 15.3.
Main()
обычно ничего не возвращает. В любом случае, если у вас естьTask<T>
(т. Е.Task
с результатом), вы можете использоватьResult
вместоWait()
. – svick 16 July 2013 в 09:50