JWT аутентификация в Java
Javaican 21.04.2025
JWT (JSON Web Token) представляет собой открытый стандарт (RFC 7519), который определяет компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Эта информация. . .
Спринты Agile: Планирование, выполнение, ревью и ретроспектива
EggHead 21.04.2025
Спринты — сердцевина Agile-методологии, позволяющая командам создавать работающий продукт итерационно, с постоянной проверкой гипотез и адаптацией к изменениям. В основе концепции спринтов лежит. . .
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров
Programma_Boinc 21.04.2025
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров.
3 марта 2025 года, в результате обобщенного поиска простых чисел Ферма в PrimeGrid был найден. . .
Система статов в Unity
GameUnited 20.04.2025
Статы — фундаментальный элемент игрового дизайна, который определяет характеристики персонажей, предметов и других объектов в игровом мире. Будь то показатель силы в RPG, скорость передвижения в. . .
Статические свойства и методы в TypeScript
run.dev 20.04.2025
TypeScript прочно занял своё место в системе современной веб-разработки. Этот строго типизированный язык программирования не просто расширяет возможности JavaScript — он делает разработку более. . .
Batch Transform и Batch Gizmo Drawing API в Unity
GameUnited 20.04.2025
В мире разработки игр и приложений на Unity производительность всегда была критическим фактором успеха. Создатели игр постоянно балансируют между визуальной привлекательностью и плавностью работы. . .
Звук в Unity: Рандомизация с Audio Random Container
GameUnited 20.04.2025
В современных играх звуковое оформление часто становится элементом, который либо полностью погружает игрока в виртуальный мир, либо разрушает атмосферу за считанные минуты. Представьте: вы исследуете. . .
Максимальная производительность C#: Советы, тестирование и заключение
stackOverflow 20.04.2025
Погружение в мир микрооптимизаций C# открывает перед разработчиком целый арсенал мощных техник. Но как определить, где и когда их применять? Ответ начинается с точных измерений и профилирования.
. . .
Максимальная производительность C#: Предсказание ветвлений
stackOverflow 20.04.2025
Третий ключевой аспект низкоуровневой оптимизации — предсказание ветвлений. Эта тема менее известна среди разработчиков, но её влияние на производительность может быть колоссальным. Чтобы понять. . .
Максимальная производительность C#: Векторизация (SIMD)
stackOverflow 20.04.2025
Помимо работы с кэшем, другим ключевым аспектом низкоуровневой оптимизации является векторизация вычислений. SIMD (Single Instruction, Multiple Data) позволяет обрабатывать несколько элементов данных. . .
Инструкции верхнего уровня (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];
}
}
Последнее обновление: 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#, когда столкнулся с проблемой: консоль показывала:
ошибка 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
Содержание
- Структура программы на C#
- Инструкции
- Блоки кода
- Комментарии
- Файл проекта .*cproj
- Итого
При знакомстве с Visual Studio мы также имели возможность познакомиться и с полной структурой программы на C#. Теперь, когда мы определились с инструментом для работы, можно полностью погрузиться в мир программирования на C# и в этой части мы рассмотрим структуру программы.
Любая программа на C# состоит из одного или нескольких файлов. Например, даже для первой программы на C# создаются такие файлы как Program.cs и [Имя_проекта].csproj. В файлах с расширением *.cs содержится код программы.
Внутри файла Program.cs в зависимости от шаблона по которому создается приложение мы можем один из двух вариантов кода:
C# 9 и более поздние версииC# до версии 9
Console.WriteLine("Hello, World");
namespace HelloWorld
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World");
}
}
}
В первом случае (для C# 9 и более поздних версий) программа использует инструкции верхнего уровня (Top-Level Statement, также можно встретить название «Операторы верхнего уровня»). Возможность использования инструкций верхнего уровня появилась, начиная с версии C# 9 и позволяет нам избавиться от некоторых формальностей при написании приложений. В любом случае, наша программа будет работать абсолютно одинаково, что в первом, что во втором случае — в консоль будет выведено сообщение «Hello, World!». При этом, в случае использования инструкций верхнего уровня мы сразу видим перед собой главный строительный блок любого приложения — инструкцию
Console.WriteLine("Hello, World");
Как отключить операторы верхнего уровня в Visual Studio
Использовать или не использовать операторы верхнего уровня — это вопрос только ваших личных предпочтений. Кто-то хочет видеть на экране весь код приложения и операторы верхнего уровня в этом случае не нужны, а кому-то проще и удобнее сразу видеть суть приложения без лишних формальностей. Чтобы определить будут ли использоваться в вашем приложении операторы верхнего уровня, необходимо при создании нового проекта использовать следующую настройку:
Если указанная на рисунке настройка выбрана, то в результате сформируется шаблон приложения со всеми операторами и инструкциями (как в C# до версии 9), если же настройка отключена, то сформируется шаблон, использующий операторы верхнего уровня.
Инструкции
Инструкции — это какое-то действие, которое мы просим программу выполнить. Это может быть вывод текста на экран, математическая операция, присвоение значения переменной и так далее. Любая инструкция в языке C# оканчивается символом «точка с запятой». Хорошим тоном в программировании считается, когда одна инструкция занимает одну строку или же, если инструкция большая (например, содержит цепочку вызовов каких-то методов) располагается на нескольких строках и умещается в ширину экрана.
Хороший пример кодаПлохой пример кода
Console.WriteLine("Введите своё имя: ");
string name = Console.ReadLine();
Console.WriteLine($"Привет, {name}!");
Console.ReadKey();
Каждая инструкция занимает одну строку кода и умещается в ширину экрана.
Console.WriteLine("Введите своё имя: "); string name = Console.ReadLine(); Console.WriteLine($"Привет, {name}!"); Console.ReadKey();
Все инструкции размещены в одной строке, что значительно усложняет чтение кода
Несколько инструкций могут объединяться в блоки кода.
Блоки кода
Блоки кода в C# заключаются в фигурные скобки ({...}). Блоки кода могут использоваться для различных задач — для определения тела метода, блоки кода объединяют различные типы данных внутри пространства имен одни блоки кода могут содержать внутри себя другие блоки и т.д. Использование блоков кода прекрасно демонстрируется во втором случае создания программы в Visual Studio без использования операторов верхнего уровня:
Комментарии
Ещё один важный элемент любой программы — это комментарии. Комментарий — это обычный текст, который не используется компилятором при сборке, однако помогает программисту сделать код более понятным. Комментарии в C# бывают однострочными и многострочными. Однострочный комментарий начинается с символов //, занимает одну строку и может размещаться на отдельной строке или после инструкции. Например, мы могли бы добавить в наше первое приложение такие комментарии:
Console.WriteLine("Введите своё имя: "); //вывод текста
string name = Console.ReadLine(); //считываем имя пользователя в переменную name
Console.WriteLine($"Привет, {name}!"); //выводим на экран приветствие
Console.ReadKey(); //ждем, пока пользователь нажмет какую-нибудь клавишу
здесь все комментарии располагаются сразу после инструкций. Иногда бывает необходимым оставить в качестве комментария большой объем текста или «закомментировать» блок кода, чтобы он не выполнялся при работе приложения. Для таких целей используются многострочные комментарии, которые начинаются с символов /* и заканчиваются символами */. Например, дадим небольшое описание нашей программе в виде многострочного комментария:
/*
Эта программа просит пользователя ввести своё имя и выводит приветствие на экран
Код взят с сайта http://csharp.webdelphi.ru
По всем вопросам работы с программой обращаться по адресу...
*/
namespace HelloWorld
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Введите своё имя: "); //вывод текста
string name = Console.ReadLine(); //считываем имя пользователя в переменную name
Console.WriteLine($"Привет, {name}!"); //выводим на экран приветствие
Console.ReadKey(); //ждем, пока пользователь нажмет какую-нибудь клавишу
}
}
}
С кодом приложения немного разобрались. Теперь переключим наше внимание на второй важный файл нашей программы — файл проекта с расширение *.cproj
Файл проекта .*cproj
Каждый проект C# содержит файл проекта. В этом файле содержится основная информация о конфигурации проекта. Посмотрим на содержимое этого файла. Для этого, в обозревателе решений Visual Studio необходимо кликнуть правой кнопкой мыши по названию проекта и в контекстном меню выбрать пункт «Изменить файл проекта»:
В редакторе кода мы увидим следующий текст:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net9.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project>
Это обычный файл в формате xml в котором может содержаться довольно много различной информации о проекте. Рассмотрим основные элементы этого файла проекта и что они означают:
OutputType |
определяет тип выходного файла приложения (сборки). Exe — создается файл с расширением *.exe, который мы можем запустить на выполнение двойным кликом мышки. Dll — на выходе получим библиотеку с расширением *.dll, которую можно будет подключать к другим проектам. По умолчанию мы создаем exe-файл |
TargetFramework |
Целевая платформа под которую будет собираться проект. В данном случае наш проект «нацелен» на платформу .NET 9. Со всеми возможными вариантами этого параметра можно ознакомиться в справке Microsoft. |
ImplicitUsings |
используется для включения или отключения неявных директив global using в проектах C#, предназначенных для .NET 6 или более поздней версии, и C# 10 или более поздней версии. |
Nullable |
Для C# 8.0 и выше (не путать с .NET 8) позволяет включать или отключать так называемый nullable-контекст. О том, что это такое и зачем нужно мы также поговорим далее, когда разберемся с основными типами данных C# |
Если Вы используете для работы Visual Studio, то эти и другие настройки проекта можно посмотреть в более удобном виде в свойствах проекта:
Итого
Итак, на примере простенькой программы мы рассмотрели структуру приложения в C# — изучили основные «строительные блоки» приложения такие как инструкции, блоки кода, комментарии. А также немного познакомились с файлом проекта и его некоторыми настройками. Теперь можно приступать созданию приложение чуть сложнее, чем обычный «Hello, world»
