.NET Aspire и cloud-native приложения C#
stackOverflow 24.05.2025
. NET Aspire — новый продукт в линейке Microsoft, который вызвал настоящий ажиотаж среди разработчиков облачных приложений. Компания называет его «опинионированным, облачно-ориентированным стеком для. . .
Python и OpenCV для распознавания и обнаружения лиц
AI_Generated 24.05.2025
Python — язык, заслуживший любовь миллионов разработчиков своей простотой и выразительностью, а OpenCV (Open Source Computer Vision Library) — библиотека компьютерного зрения с открытым исходным. . .
Брокер NATS в C#
UnmanagedCoder 24.05.2025
NATS (Neural Autonomic Transport System) — это легковесная система обмена сообщениями, которая отлично вписывается в мир современных распределённых приложений. Если вы когда-нибудь пытались построить. . .
Оптимизация производительности Express.js бэкенда
Reangularity 23.05.2025
Express. js заслуженно остаётся одним из самых популярных инструментов для создания бэкенда, но даже он не застрахован от проблем с производительностью. Многие разработчики сталкиваются с ситуацией,. . .
Продвинутая обработка данных с LINQ в C#
stackOverflow 23.05.2025
LINQ (Language Integrated Query) — это фундаментальное изменение парадигмы работы с данными в C#. Простые запросы Where и Select знакомы любому разработчику, но настоящая мощь LINQ раскрывается в. . .
Инфраструктура PKI и сертификатов безопасности
Mr. Docker 23.05.2025
PKI (Public Key Infrastructure) — это невидимый фундамент цифрового доверия, без которого современный интернет просто рассыпался бы как карточный домик. За этой аббревиатурой скрывается целый. . .
Аутентификация OAuth в Python
py-thonny 22.05.2025
OAuth (Open Authorization) — это целый стандарт для делегированного доступа. Звучит занудно? Давайте проще: OAuth позволяет приложениям получать доступ к информации пользователя на сторонних сервисах. . .
Хеширование и соль паролей в веб-приложениях C#
stackOverflow 22.05.2025
Когда-то в начале своей карьеры я тоже грешил простейшими подходами к хранению паролей – MD5-хеширование казалось верхом защиты. Но технологии не стоят на месте, вычислительные мощьности растут, и. . .
Генераторы Python для эффективной обработки данных
AI_Generated 21.05.2025
В Python существует инструмент настолько мощный и в то же время недооценённый, что я часто сравниваю его с тайным оружием в арсенале программиста. Речь идёт о генераторах — одной из самых элегантных. . .
Чем заменить Swagger в .NET WebAPI
stackOverflow 21.05.2025
Если вы создавали Web API на . NET в последние несколько лет, то наверняка сталкивались с зелёным интерфейсом Swagger UI. Этот инструмент стал практически стандартом для документирования и. . .
Инструкции верхнего уровня (Top-Level Statement) позволяют отказаться от некоторых формальностей при написании приложений и сделать код проще. Возможно, это не очень будет заметно при написании сложных приложений, но может хорошо сэкономить время при проведении исследований, создании небольших утилит и прототипов.
Минимальная платформа с полной поддержкой: нет ограничений.
Так обычно выглядит точка входа в консольное приложение:
namespace Prototype { public static class Program { public static int Main(string[] args) { bool success = DoSomeJob(); return success ? 1 : -1; } } }
В данном случае C# 9 позволяет отказаться от таких шаблонных деталей как namespace, class Program, метод Main(…) и сразу начать писать код точки входа.
var result = DoSomeJob(); return result ? 1 : -1;
Такой код и называется инструкциями верхнего уровня.
Возможности
В инструкциях верхнего уровня можно:
- обращаться к переменной string[] args, представляющей собой массив аргументов переданных через командную строку.
- возвращать целочисленное (int) значение.
- вызывать асинхронные методы.
- объявлять локальные методы.
- объявлять свои пространства имен и классы, но только после кода инструкций верхнего уровня.
При сборке проекта компилятор в глобальном пространстве имен (global namespace) автоматически создаст класс Program c одним из четырех вариантов метода Main(…), в зависимости от написанного кода:
- void Main(string[] args)
- int Main(string[] args)
- Task Main(string[] args)
- Task<int> Main(string[] args)
Стоит отметить, что классы, объявленные в файле с инструкциями верхнего уровня будут обычными, а не внутренними классами Program, независимо от наличия собственного пространства имен.
Рассмотрим описанные возможности на следующем примере:
using System; using System.Threading.Tasks; using DemoApp.Reader; var reader = new FileReader(); string content = await reader.Read(GetFileName()); Console.WriteLine(content); return content.Length; string GetFileName() => args[0]; namespace DemoApp.Reader { public class FileReader { public async Task Read(string fileName) => await System.IO.File.ReadAllTextAsync(fileName); } }
Результат декомпиляции собранного проекта будет выглядеть следующим образом:
using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; using DemoApp.Reader; [CompilerGenerated] internal class Program { private static async Task<int> <Main>$(string[] args) { FileReader reader = new FileReader(); string content = await reader.Read(GetFileName()); Console.WriteLine(content); return content.Length; string GetFileName() { return args[0]; } } }
Отдельно, в пространстве имен DemoApp.Reader, можно найти класс FileReader. Его код, по сути, ничем не отличается от его объявления выше.
Ограничения
- В проекте может быть только один файл с инструкциями верхнего уровня.
- В проекте может быть только или объялена классическая точка входа (метод Main(…)) или указаны инструкции верхнего уровня.
Особенности
Несмотря на то, что класс Program автоматически генерируемый, на этапе разработки он доступен в приложении как и любой другой класс.
Кроме того, его можно расширить, добавив свои методы. Для этого необходимо самостоятельно объявить internal partial class Program. Соответственно, добавленные статические методы, будут также доступны в коде инструкций верхнего уровня.
Перепишем пример выше, заменив локальный метод GetFileName() на публичный статический:
using System; using System.Threading.Tasks; using DemoApp.Reader; var reader = new FileReader(); string content = await reader.Read(GetFileName(args)); Console.WriteLine(content); return content.Length; internal partial class Program { public static string GetFileName(string[] args) => args[0]; } namespace DemoApp.Reader { public class FileReader { public async Task Read(string fileName) => await System.IO.File.ReadAllTextAsync(fileName); } }
Результат декомпиляции будет следующий:
// Program using System; using System.Threading.Tasks; using DemoApp.Reader; internal class Program { private static async Task<int> <Main>$(string[] args) { FileReader reader = new FileReader(); string content = await reader.Read(GetFileName(args)); Console.WriteLine(content); return content.Length; } public static string GetFileName(string[] args) { return args[0]; } }
Я создавал свою первую игру на C#, когда столкнулся с проблемой: консоль показывала:
ошибка cs8803: операторы верхнего уровня должны предшествовать объявлениям пространства имен и типов.
с использованием System; >
Это игра с Flappy Bird, и это сценарий для создания труб, через которые игрок должен прыгать.
Может ли кто-нибудь подсказать проблему? вот код:
Код: Выделить всё
public class SpawnPipeScript : MonoBehaviour
{
public GameObject Pipes;
public float spawnRate = 2;
private float timer = 0;
public float heightOffset = 10;
}
// Start is called before the first frame update
void Start()
{
spawnPipe();
}
// Update is called once per frame
void Update()
{
if (timer < spawnRate)
{
timer = timer + Time.deltaTime;
}
else
{
spawnPipe();
timer = 0;
}
}
void spawnPipe()
{
float lowestPoint = transform.position.y - heightOffset;
float highestPoint = transform.position.y + heightOffset;
{
Instantiate(Pipes, new Vector3(transform.position.x, Random.Range(lowestPoint, highestPoint), 0), transform.rotation);
}
}
Код
Подробнее здесь: https://stackoverflow.com/questions/792 … clarations
Последнее обновление: 10.11.2021
Точкой входа в программу на языке C# является метод Main. Именно с этого метода начинается выполнение программы на C#. И программа на C# должна обязательно иметь метод Main
. Однако может возникнуть вопрос, какой еще метод Main, если,
например, Visual Studio 2022 по умолчанию создает проект консольного приложения со следующим кодом:
// See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!");
И эта программа никаких методов Main не содержит, но при этом нормально выполняется и выводит на консоль строку «Hello, World!», как и запланировано. Это так называемая программа
верхнего уровня (top-level program). А вызов Console.WriteLine("Hello, World!")
представляет инструкцию вехнего уровня (top-level statement)
Однако в реальности этот код неявно помещается компилятором в метод Main, который, в свою очередь, помещается в класс Program.
В действительности название класса может быть любым (как правило, это класс Program, собственно поэтому генерируемый по умолчанию файл кода
называется Program.cs). Но метод Main является обязательной частью консольного приложения. Поэтому выше представленный код фактически
эквивалентен следующей программе:
class Program { static void Main(string[] args) { // See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!"); } }
Определение метода Main обязательно начинается с модификатора static
, которое указывает, что метод Main —
статический. Позже мы подробнее разберем, что все это значит.
Возвращаемым типом метода Main обязательно является тип void. Кроме того, в качестве параметра он принимает массив строк — string[] args
— в реальной программе это те параметры,
через которые при запуске программы из консоли мы можем передать ей некоторые значения. Внутри метода располагаются действия, которые выполняет программа.
До Visual Studio 2022 все предыдущие студии создавали по умолчанию примерно такой код. Но начиная с Visual Studio 2022
нам необязательно вручную определять класс Program и в нем метод Main — компилятор генерирует их самостоятельно.
Если мы определяем какие-то переменные, константы, методы и обращаемся к ним, они помещаются в метод Main. Например, следующая программа верхнего уровня
string hello = "Hello METANIT.COM"; Print(hello); void Print(string message) { Console.WriteLine(message); }
будет аналогична следующей программе:
class Program { static void Main(string[] args) { string hello = "Hello METANIT.COM"; Print(hello); void Print(string message) { Console.WriteLine(message); } } }
Если определяются новые типы, например, классы, то они помещаются вне класса Program. Например, код:
Person tom = new(); tom.SayHello(); class Person { public void SayHello() =>Console.WriteLine("Hello"); }
будет аналогичен следующему
class Program { static void Main(string[] args) { Person tom = new(); tom.SayHello(); } } class Person { public void SayHello() => Console.WriteLine("Hello"); }
Однако надо учитывать, что опредления типов (в частности классов) должны идти в конце файла после инструкций верхнего уровня. То есть:
// инструкции верхнего уровня (top-level statements) Person tom = new(); tom.SayHello(); // определение класса идет после инструкций верхнего уровня class Person { public void SayHello() => Console.WriteLine("Hello"); }
Таким образом, мы можем продолжать писать программы верхнего уровня без явного
определения метода Main. Либо мы можем явным образом определить метод Main и класс Program:
И этот код будет выполняться аналогичным образом, как если бы мы не использовали класс Program и метод Main.
Всем привет.
Ребята, пожалуйста, спасите от разочарования. Вчера я считал, много лет считал, что C# — лучший ЯП по моим меркам. Сегодня, с выходом C# 10, мои представления здорово так пошатнулись.
Итак. Создаем консольный проект .NET 6.
Видим одну единственную инструкцию:
Console.WriteLine("Hello, World!");
Если раньше, в C# 9, хотя бы к System нужно было обращаться, то в C# 10, вообще не нужно.
Оказывается, в C# 10 появились неявные директивы using. Вот они определены, а для того, дабы написать то, как мы долгие годы писали, с using, классами и точкой входа, нужно плясать с бубном. К примеру, создать проект .NET 5, а в настройках поменять на .NET 6.
Объясните, растолкуйте, пожалуйста! Как понять? Это насильное навязывание нового стиля кодирования?
Т.е, если я хочу писать на C# 10, но я хочу писать полноценно, а не абы как. Мне что, устраивать пляски, чтобы оно работало?
Или как в VS отказаться от неявных директив и вздохнуть свободно?
Заранее благодарен!
-
Вопрос задан
-
1064 просмотра
Пригласить эксперта
Ну вообще это удобно. и я не вижу каких-то причин. чтобы писать по старому.
Но если очень сильно хочется — ты можешь создать свой собственный шаблон, в котором будет создаваться старый public static void Main и без неявных юзингов.
Вот так выключаются global usings:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
</PropertyGroup>
</Project>
Вот так создавать свой шаблон:
https://docs.microsoft.com/ru-ru/dotnet/core/tools…
Войдите, чтобы написать ответ
-
Показать ещё
Загружается…