Loading AI tools
объектно-ориентированный язык программирования Из Википедии, свободной энциклопедии
C# (произносится си шарп) — объектно-ориентированный язык программирования общего назначения. Разработан в 1998—2001 годах группой инженеров компании Microsoft под руководством Андерса Хейлсберга и Скотта Вильтаумота[6] как язык разработки приложений для платформы Microsoft .NET Framework и .NET Core. Впоследствии был стандартизирован как ECMA-334 и ISO/IEC 23270.
С# | |
---|---|
Класс языка | |
Появился в | 2001 |
Автор | Андерс Хейлсберг |
Разработчик | .NET Foundation |
Расширение файлов |
.cs или .csx |
Выпуск | 12 (14 ноября 2023 года) |
Система типов | статическая, динамическая, строгая, безопасная, вывод типов |
Основные реализации | .NET Framework, Mono, .NET, DotGNU (заморожен), Universal Windows Platform |
Диалекты | Cω, Spec#, Polyphonic C#[англ.], Enhanced C# |
Испытал влияние | C++, Java[1][2][3], Delphi, Модула-3 и Smalltalk |
Повлиял на | Cω, F#, Nemerle, Vala, Windows PowerShell, Kotlin |
Лицензия |
Компилятор Roslyn: лицензия MIT[4] Компилятор Mono: dual GPLv3 and MIT/X11 |
Сайт | docs.microsoft.com/ru-ru… |
Платформа | Common Language Infrastructure |
Медиафайлы на Викискладе |
C# относится к семье языков с C-подобным синтаксисом, из них его синтаксис наиболее близок к C++ и Java. Язык имеет статическую типизацию, поддерживает полиморфизм, перегрузку операторов (в том числе операторов явного и неявного приведения типа), делегаты, атрибуты, события, переменные, свойства, обобщённые типы и методы, итераторы, анонимные функции с поддержкой замыканий, LINQ, исключения, комментарии в формате XML.
Переняв многое от своих предшественников — языков C++, Delphi, Модула, Smalltalk и, в особенности, Java — С#, опираясь на практику их использования, исключает некоторые модели, зарекомендовавшие себя как проблематичные при разработке программных систем, например, C# в отличие от C++ не поддерживает множественное наследование классов (между тем допускается множественная реализация интерфейсов).
С# разрабатывался как язык программирования прикладного уровня для CLR и, как таковой, зависит, прежде всего, от возможностей самой CLR. Это касается, прежде всего, системы типов С#, которая отражает BCL. Присутствие или отсутствие тех или иных выразительных особенностей языка диктуется тем, может ли конкретная языковая особенность быть транслирована в соответствующие конструкции CLR. Так, с развитием CLR от версии 1.1 к 2.0 значительно обогатился и сам C#; подобного взаимодействия следует ожидать и в дальнейшем (однако, эта закономерность была нарушена с выходом C# 3.0, представляющего собой расширения языка, не опирающиеся на расширения платформы .NET). CLR предоставляет С#, как и всем другим .NET-ориентированным языкам, многие возможности, которых лишены «классические» языки программирования. Например, сборка мусора не реализована в самом C#, а производится CLR для программ, написанных на C#, точно так же, как это делается для программ на VB.NET, J# и др.
Название «Си шарп» (от англ. sharp — диез) происходит от буквенной музыкальной нотации, где латинской букве C соответствует нота До, а знак диез (англ. sharp) означает повышение соответствующего ноте звука на полутон[7], что аналогично названию языка C++, где «++» обозначает инкремент переменной. Название также является игрой с цепочкой C → C++ → C++++(C#), так как символ «#» можно представить состоящим из 4 знаков «+»[8].
Из-за технических ограничений на отображение (стандартные шрифты, браузеры и т. д.), а также из-за того, что знак диеза ♯ не представлен на стандартной клавиатуре компьютера, при записи имени языка программирования используют знак решётки (#)[9]. Это соглашение отражено в Спецификации языка C# ECMA-334[10]. Тем не менее, на практике (например, при размещении рекламы и коробочном дизайне[11]), «Майкрософт» использует знак диеза.
Названия языков программирования не принято переводить, поэтому язык называют, используя транскрипцию, — «Си шарп».
C# стандартизирован в ECMA (ECMA-334)[12] и ISO (ISO/IEC 23270)[13].
Известно как минимум о трёх независимых реализациях C#, базирующихся на этой спецификации и находящихся в настоящее время на различных стадиях разработки:
На протяжении разработки языка C# было выпущено несколько его версий:
Версия | Нововведения |
---|---|
C# 2.0 |
|
C# 3.0 |
|
C# 4.0 |
|
C# 5.0 |
|
C# 6.0 |
|
C# 7.0[17] |
|
C# 8.0 |
|
C# 9.0 |
|
C# 10.0 |
|
C# 11.0 |
|
Проект C# был начат в декабре 1998 и получил кодовое название COOL (C-style Object Oriented Language). Версия 1.0 была анонсирована вместе с платформой .NET в июне 2000 года, тогда же появилась и первая общедоступная бета-версия; C# 1.0 окончательно вышел вместе с Microsoft Visual Studio .NET в феврале 2002 года.
Первая версия C# напоминала по своим возможностям Java 1.4, несколько их расширяя: так, в C# имелись свойства (выглядящие в коде как поля объекта, но на деле вызывающие при обращении к ним методы класса), индексаторы (подобные свойствам, но принимающие параметр как индекс массива), события, делегаты, циклы foreach
, структуры, передаваемые по значению, автоматическое преобразование встроенных типов в объекты при необходимости (boxing), атрибуты, встроенные средства взаимодействия с неуправляемым кодом (DLL, COM) и прочее.
Кроме того, в C# решено было перенести некоторые возможности C++, отсутствовавшие в Java: беззнаковые типы, перегрузку операторов (с некоторыми ограничениями, в отличие от C++), передача параметров в метод по ссылке, методы с переменным числом параметров, оператор goto
(с ограничениями). Также в C# оставили ограниченную возможность работы с указателями — в местах кода, специально обозначенных словом unsafe
и при указании специальной опции компилятору.
Проект спецификации C# 2.0 впервые был опубликован Microsoft в октябре 2003 года; в 2004 году выходили бета-версии (проект с кодовым названием Whidbey), C# 2.0 окончательно вышел 7 ноября 2005 года вместе с Visual Studio 2005 и .NET 2.0.
yield
, подобно Python и Ruby.return obj1 ?? obj2;
означает (в нотации C# 1.0) return obj1!=null ? obj1 : obj2;
.int? i = null;
), представляющие собой те же самые типы-значения, способные принимать также значение null
. Такие типы позволяют улучшить взаимодействие с базами данных через язык SQL.В июне 2004 года Андерс Хейлсберг впервые рассказал на сайте Microsoft о планируемых расширениях языка в C#3.0[19]. В сентябре 2005 года вышли проект спецификации C# 3.0 и бета-версия C# 3.0, устанавливаемая в виде дополнения к существующим Visual Studio 2005 и .NET 2.0. Окончательно эта версия языка вошла в Visual Studio 2008 и .NET 3.5.
В C# 3.0 появились следующие радикальные добавления к языку:
select, from, where
, позволяющие делать запросы из XML документов, коллекций и т. п. Эти запросы имеют сходство с запросами SQL и реализуются компонентом LINQ. (Сама фраза «language integrated query» переводится «запрос, интегрированный в язык».)Customer c = new Customer(); c.Name = "James"; c.Age=30;
Customer c = new Customer { Name = "James", Age = 30 };
listOfFoo.Where(delegate(Foo x) { return x.size > 10; });
listOfFoo.Where(x => x.size > 10);
var
. Затем уже при компиляции компилятор сам выводит тип данных исходя из присвоенного значения:var x = "hello";
вместо string x = "hello";
var x = new { Name = "James" };
this
при первом параметре статической функции статического класса.public static class StringExtensions
{
public static int ToInt32(this string val)
{
return Int32.Parse(val);
}
}
// ...
string s = "10";
int x = s.ToInt32();
public string Name { get; private set; }
C# 3.0 совместим с C# 2.0 по генерируемому MSIL-коду; улучшения в языке — чисто синтаксические и реализуются на этапе компиляции. Например, многие из интегрированных запросов LINQ можно осуществить, используя безымянные делегаты в сочетании с предикатными методами над контейнерами наподобие List.FindAll
и List.RemoveAll
.
Превью C# 4.0 было представлено в конце 2008 года, вместе с CTP-версией Visual Studio 2010.
Visual Basic 10.0 и C# 4.0 были выпущены в апреле 2010 года, одновременно с выпуском Visual Studio 2010.
Task
, TaskFactory
, Parallel
MemoryCache
, который предназначен для кэширования контента. Он похож на класс Cache
ASP.NET, но его можно использовать при написании веб- / графических / консольных приложений.Примеры:
dynamic calc = GetCalculator();
int sum = calc.Add(10, 20); // Динамический вызов
public void SomeMethod(int x, int y = 5, int z = 7); // Опциональные параметры
Новые возможности в версии 5.0
async
и await
) — как реализация шаблона TAP.Новые возможности в версии 6.0
?.
и ?[]
:int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public string First { get; set; } = "Jane";
public string First { get; } = "Jane";
var numbers = new Dictionary<int, string> {
[7] = "seven",
[9] = "nine",
[13] = "thirteen"
};
String.Format()
, например:var s = String.Format("{0} is {1} year{{s}} old", p.Name, p.Age);
теперь можно размещать код прямо в строке:
var s = $"{p.Name} is {p.Age} year{{s}} old";
catch
:try { … } catch (Exception e) when (Log(e)) { … }
using static System.Console;
using static System.Math;
class Program
{
static void Main()
{
WriteLine(Sqrt(3*3 + 4*4));
}
}
nameof
. Новый оператор, который возвращает компактное строковое представление для переданного в качестве аргумента типа:WriteLine(nameof(person.Address.ZipCode)); // prints "ZipCode"
await
внутри блоков catch
и finally
:Resource res = null;
try
{
res = await Resource.OpenAsync(…); // You could do this.
}
catch(ResourceException e)
{
await Resource.LogAsync(res, e); // Now you can do this …
}
finally
{
if (res != null) await res.CloseAsync(); // … and this.
}
Новые возможности в версии 7.0[17]
out
-переменные, которые позволяют объявить переменные сразу в вызове метода (причем областью видимости для таких переменных является внешний блок):p.GetCoordinates(out int x, out int y);
pattern
), который представляет собой синтаксическую конструкцию, позволяющую проверить соответствие переменной определённой форме и извлечь из неё информацию.is
(is
теперь может использоваться не только с типом, но и с шаблоном — в качестве правого аргумента)switch
. Варианты использования switch
были расширены, теперь можно:
case
;case
(используя ключевое слово when
).ValueTuple
) и синтаксис работы с данными этого типа:(string, string, string) LookupName(long id) // возвращаемый тип - кортеж
{
... // инициализируем данные
return (first, middle, last); // литерал кортежа
}
_
) в числовых литералах.ref
. Теперь можно возвратить данные из метода или сохранить их в локальной переменной по ссылке.expression-bodied functions
), теперь применим для сеттеров, геттеров, конструкторов и деструкторов.throw
-выражения. Теперь можно использовать throw
в функциях, сжатых до выражений (expression-bodied functions
):public string GetLastName() => throw new NotImplementedException();
Новые возможности в версии 8.0[21]
readonly
. Был создан для обозначения члена, который не изменит состояние.public enum Rainbow
{
Red,
Orange,
Yellow,
Green,
Blue,
Indigo,
Violet
}
public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
{ variable : value } => ...
.(value1, value2,..) => ...
using
. Это объявление переменной, которому предшествует ключевое слово using
. Оно сообщает компилятору, что объявляемая переменная должна быть удалена в конце области видимости.static
.IDisposable
(как и любые другие интерфейсы). Поэтому чтобы удалить ref struct
, необходим доступный void Dispose()
.null
. Теперь, чтобы указать, что переменная типа значений допускает значение null
, необходимо поставить к имени типа ?
IAsyncEnumerable<T>
. А во-вторых конструкция foreach
с await
.public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{
for (int i = 0; i < 20; i++)
{
await Task.Delay(100);
yield return i;
}
}
// or
await foreach (var number in GenerateSequence())
{
Console.WriteLine(number);
}
System.IAsyncDisposable
. Операнд выражения using
может реализовывать IDisposable
или IAsyncDisposable
. В случае IAsyncDisposable
компилятор создает код для await
, возвращенного Task
из IAsyncDisposable.DisposeAsync
.^
и ..
, а также System.Index
и System.Range
??=
можно использовать для присваивания значения правого операнда левому операнду только в том случае, если левый операнд имеет значение null
.List<int> numbers = null;
int? i = null;
numbers ??= new List<int>();
numbers.Add(i ??= 17);
numbers.Add(i ??= 20);
Console.WriteLine(string.Join(" ", numbers)); // output: 17 17
Console.WriteLine(i); // output: 17
System.Span<T>
или System.ReadOnlySpan<T>
, то его можно использовать в других выражениях.Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
Console.WriteLine(ind); // output: 1
$
и @
в интерполированных строках verbatim теперь может быть любым.Новые возможности в версии 9.0[22]
record
для определения ссылочного типа, предоставляющего функционал инкапсуляции данных. public record Person(string FirstName, string LastName);
with
возможно создание копии с изменёнными значениями указанных свойств и полей.init
— для задания значений свойств класса при инициализации. public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
};
Main
.and
, or
, not
).new
, если он известен заранее private List<Person> persons = new();
Новые возможности в версии 10.0[23]
global
появилась возможность определить пространства имён, которые будут импортированы глобально во всех файлах проекта. global using System;
global using System.Collections.Generic;
namespace MyNamespace;
public struct Point
{
public int X { get; set; } = 0;
public int Y { get; set; } = 0;
}
sealed
, что предотвращает их реализацию другими интерфейсами. public sealed interface IMyInterface { }
switch
и if
. int[] numbers = { 1, 2, 3, 4, 5 };
bool isThreeElementArray = numbers is [_, _, _];
public record struct Point(int X, int Y);
[MyCustom]
void LocalFunction() { }
var increment = (int x) => x + 1;
async/await
. Улучшена работа с асинхронными методами, включая более эффективное управление памятью и потоками.Новые возможности в версии 11.0[24]
public interface IMyInterface<TSelf, TOther, TResult>
where TSelf : IMyInterface<TSelf, TOther, TResult>
{
static abstract TResult operator +(TSelf left, TOther right);
}
checked
и unchecked
арифметические операторы, что позволяет компилятору вызывать правильный вариант на основе контекста. public static checked int operator +(MyType left, MyType right)
{
left.Value + right.Value;
}
>>>
, который выполняет сдвиг вправо без знака, упрощая работу с целочисленными типами. int result = -8 >>> 2;
int
, что делает использование универсальных математических интерфейсов более гибким. MyType value = new MyType();
value >>= 3;
System.IAdditionOperators<TSelf, TOther, TResult>
, позволяют типам реализовывать математические операции более последовательно и удобно. public struct MyNumber : IAdditionOperators<MyNumber, MyNumber, MyNumber>
{
public static MyNumber operator +(MyNumber left, MyNumber right)
{
new MyNumber(left.Value + right.Value);
}
}
public struct Point
{
public int X { get; set; } = 0;
public int Y { get; set; } = 0;
}
Новые возможности в версии 12.0[25]
public interface IMyInterface<TSelf, TOther, TResult>
where TSelf : IMyInterface<TSelf, TOther, TResult>
{
static abstract TResult operator +(TSelf left, TOther right);
static virtual TResult Add(TSelf left, TOther right)
{
return left + right;
}
}
ImmutableArray
, которая обеспечивает неизменяемость элементов и повышение производительности. var immutableArray = ImmutableArray.Create(1, 2, 3, 4);
readonly struct
и ref readonly struct
, для оптимизации работы с памятью. public readonly struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y)
{
X = x;
Y = y;
}
}
public record Person(string Name)
{
public virtual string GetName() => Name;
}
public record Employee(string Name, int EmployeeId) : Person(Name)
{
public override string GetName() => $"{Name} (ID: {EmployeeId})";
}
public void PrintValues(params int[] values)
{
foreach (var value in values)
{
Console.WriteLine(value);
}
}
PrintValues(1, 2, 3, 4);
Ниже представлен код классической программы «Hello world» на C# для консольного приложения:
Console.WriteLine("Hello World!");
и код этой же программы для приложения Windows Forms:
namespace WindowsForms;
public class Program
{
[STAThread]
public static void Main() => new DemoForm().ShowDialog();
}
public class DemoForm : Form
{
Label label = new Label();
public DemoForm()
{
label.Text = "Hello World!";
this.Controls.Add(label);
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = Color.White;
this.FormBorderStyle = FormBorderStyle.Fixed3D;
}
}
Существует несколько реализаций C#:
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.