Си Шарп 4.0
C# 4.0 — это версия языка программирования C# , выпущенная 11 апреля 2010 года. Microsoft 4.0 выпустила среду выполнения и среду разработки Visual Studio 2010 . [1] Основное внимание в C# 4.0 уделяется совместимости с частично или полностью динамически типизированными языками и платформами, такими как Dynamic Language Runtime и COM .
Функции
[ редактировать ]Следующие новые возможности были добавлены в C# 4.0. [2]
Динамический поиск участников
[ редактировать ]Новый псевдотип dynamic
введен в систему типов C#. Это рассматривается как System.Object
, но, кроме того, любой доступ к члену (вызов метода, поля, свойства или доступ к индексатору или вызов делегата) или применение оператора к значению такого типа разрешены без какой-либо проверки типа, и его разрешение откладывается до запуска -время. Это известно как утиная типизация . Например:
// Returns the value of Length property or field of any object
int GetLength(dynamic obj)
{
return obj.Length;
}
GetLength("Hello, world"); // a string has a Length property,
GetLength(new int[] { 1, 2, 3 }); // and so does an array,
GetLength(42); // but not an integer - an exception will be thrown in GetLength method at run-time
Вызовы динамических методов инициируются значением типа dynamic
как любой неявный или явный параметр (а не только получатель). Например:
void Print(dynamic obj)
{
System.Console.WriteLine(obj); // which overload of WriteLine() to call is decided at run-time
}
Print(123); // ends up calling WriteLine(int)
Print("abc"); // ends up calling WriteLine(string)
Динамический поиск выполняется с использованием трех различных механизмов: COM IDispatch для COM-объектов, IDynamicMetaObjectProvider
Интерфейс DLR для объектов, реализующих этот интерфейс, и отражение для всех остальных объектов. Таким образом, любой класс C# может перехватывать динамические вызовы своих экземпляров, реализуя IDynamicMetaObjectProvider
.
В случае вызовов динамических методов и индексаторов разрешение перегрузки происходит во время выполнения в соответствии с фактическими типами значений, передаваемых в качестве аргументов, но в остальном — в соответствии с обычными правилами разрешения перегрузки C#. Более того, в тех случаях, когда получатель в динамическом вызове сам по себе не является динамическим, разрешение перегрузки во время выполнения будет учитывать только те методы, которые предоставляются для объявленного типа приемника во время компиляции. Например:
class Base
{
void Foo(double x);
}
class Derived : Base
{
void Foo(int x);
}
dynamic x = 123;
Base b = new Derived();
b.Foo(x); // picks Base.Foo(double) because b is of type Base, and Derived.Foo(int) is not exposed
dynamic b1 = b;
b1.Foo(x); // picks Derived.Foo(int)
Любое значение, возвращаемое при доступе к динамическому члену, само по себе имеет тип dynamic
. Значения типа dynamic
неявно конвертируются как из любого другого типа, так и в него. В приведенном выше примере кода это позволяет GetLength
функция для обработки значения, возвращаемого вызовом Length
как целое число без явного приведения. Во время выполнения фактическое значение будет преобразовано в запрошенный тип.
Ковариантные и контравариантные параметры универсального типа
[ редактировать ] универсальных Параметры типа интерфейсов и делегатов могут быть помечены как ковариантные или контравариантные с использованием ключевых слов. out
и in
соответственно. Эти объявления затем учитываются при преобразованиях типов, как неявных, так и явных, а также во время компиляции и во время выполнения. Например, существующий интерфейс IEnumerable<T>
было переопределено следующим образом:
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
Следовательно, любой класс, реализующий IEnumerable<Derived>
для какого-то класса Derived
также считается совместимым с IEnumerable<Base>
для всех классов и интерфейсов Base
что Derived
распространяется прямо или косвенно. На практике это позволяет писать такой код, как:
void PrintAll(IEnumerable<object> objects)
{
foreach (object o in objects)
{
System.Console.WriteLine(o);
}
}
IEnumerable<string> strings = new List<string>();
PrintAll(strings); // IEnumerable<string> is implicitly converted to IEnumerable<object>
Для контрвариантности существующий интерфейс IComparer<T>
было переопределено следующим образом:
public interface IComparer<in T>
{
int Compare(T x, T y);
}
Следовательно, любой класс, реализующий IComparer<Base>
для какого-то класса Base
также считается совместимым с IComparer<Derived>
для всех классов и интерфейсов Derived
которые простираются от Base
. Это позволяет писать такой код, как:
IComparer<object> objectComparer = GetComparer();
IComparer<string> stringComparer = objectComparer;
Необязательное ключевое слово ref при использовании COM
[ редактировать ]The ref
Ключевое слово для вызывающих методов теперь является необязательным при вызове методов, предоставляемых COM- интерфейсами. Учитывая метод COM с сигнатурой
void Increment(ref int x);
вызов теперь может быть записан как
Increment(0); // no need for "ref" or a place holder variable any more
или
int x = 0;
Increment(ref x);
Необязательные параметры и именованные аргументы
[ редактировать ]В C# 4.0 представлены необязательные параметры со значениями по умолчанию, как показано в Visual Basic и C++ . Например:
void Increment(ref int x, int dx = 1)
{
x += dx;
}
int x = 0;
Increment(ref x); // dx takes the default value of 1, after the method returns x == 1
Increment(ref x, 2); // dx takes the value 2, after the method returns x == 3
Кроме того, в дополнение к необязательным параметрам можно явно указывать имена параметров при вызовах методов, что позволяет программисту выборочно передавать любое подмножество необязательных параметров для метода. Единственное ограничение состоит в том, что именованные параметры должны располагаться после неименованных параметров. Имена параметров могут быть указаны как для необязательных, так и для обязательных параметров и могут использоваться для улучшения читаемости или произвольного изменения порядка аргументов в вызове. Например:
Stream OpenFile(string name, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) { ... }
OpenFile("file.txt"); // use default values for both "mode" and "access"
OpenFile("file.txt", mode: FileMode.Create); // use default value for "access"
OpenFile("file.txt", access: FileAccess.Read); // use default value for "mode"
OpenFile(name: "file.txt", access: FileAccess.Read, mode: FileMode.Create); // name all parameters for extra readability,
// and use order different from method declaration
Дополнительные параметры упрощают взаимодействие с COM. Раньше C# приходилось передавать каждый параметр в метод компонента COM, даже те, которые не являются обязательными. Например:
object fileName = "Test.docx";
object missing = System.Reflection.Missing.Value;
doc.SaveAs(ref fileName,
ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing);
Благодаря поддержке необязательных параметров код можно сократить до
doc.SaveAs(ref fileName);
Что из-за теперь необязательного ref
Ключевое слово при использовании COM может быть сокращено до
doc.SaveAs(fileName);
Индексированные свойства
[ редактировать ]Индексированные свойства (и свойства по умолчанию) объектов COM теперь распознаются, но объекты C# по-прежнему их не поддерживают.
Ссылки
[ редактировать ]- ^ «Первый взгляд на Microsoft Visual Studio 2010» . Майкрософт .
- ^ Берроуз, Крис (2010). «C# 4.0 — новые возможности C# в .NET Framework 4» . Майкрософт . Проверено 14 июля 2023 г.
Внешние ссылки
[ редактировать ]- Берроуз, Крис (2010). «C# 4.0 — новые возможности C# в .NET Framework 4» . Майкрософт . Проверено 14 июля 2023 г.
- Спецификация языка C# 4.0