C Sharp 4.0: Difference between revisions
m wiki style; punc fix; link |
|||
(45 intermediate revisions by 38 users not shown) | |||
Line 1: | Line 1: | ||
{{short description|Version of the C# programming language}} |
|||
{{pound|C# 4.0}} |
|||
{{Correct title|title=C# 4.0|reason=hash}} |
|||
'''C# 4.0''' is |
'''C# 4.0''' is a version of the [[C Sharp (programming language)|C#]] programming language that was released on April 11, 2010. [[Microsoft]] released the 4.0 [[Run-time system|runtime]] and development environment [[Visual Studio 2010]].<ref>{{cite web|url=http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx|title=Microsoft Visual Studio 2010 First Look|website=[[Microsoft]] }}</ref> The major focus of C# 4.0 is interoperability with partially or fully dynamically typed languages and frameworks, such as the [[Dynamic Language Runtime]] and [[Component Object Model|COM]]. |
||
== Features == |
== Features == |
||
The following new features |
The following new features were added in C# 4.0.<ref>{{cite web |
||
|url=https://learn.microsoft.com/en-us/archive/msdn-magazine/2010/july/csharp-4-0-new-csharp-features-in-the-net-framework-4 |
|||
|url=http://code.msdn.microsoft.com/csharpfuture/Release/ProjectReleases.aspx?ReleaseId=1686 |
|||
|title= |
|title=C# 4.0 - New C# Features in the .NET Framework 4 |
||
|first= |
|first=Chris |
||
|last= |
|last=Burrows |
||
|year=2010 |
|||
|date=2008-10-27 |
|||
|publisher=[[Microsoft]] |
|publisher=[[Microsoft]] |
||
|accessdate= |
|accessdate=2023-07-14 |
||
}}</ref> |
}}</ref> |
||
=== Dynamic member lookup === |
=== Dynamic member lookup === |
||
A new pseudo-type <code>dynamic</code> is introduced into the C# type system. It is treated as <code>System.Object</code>, but in addition, any member access (method call, field, property, or indexer access, or a delegate invocation) or application of an operator on a value of such type is permitted without any type checking, and its resolution is postponed until run-time. For example: |
A new pseudo-type <code>dynamic</code> is introduced into the C# type system. It is treated as <code>System.Object</code>, but in addition, any member access (method call, field, property, or indexer access, or a delegate invocation) or application of an operator on a value of such type is permitted without any type checking, and its resolution is postponed until run-time. This is known as [[duck typing]]. For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
// Returns the value of Length property or field of any object |
// Returns the value of Length property or field of any object |
||
int GetLength(dynamic obj) |
int GetLength(dynamic obj) |
||
Line 27: | Line 28: | ||
GetLength("Hello, world"); // a string has a Length property, |
GetLength("Hello, world"); // a string has a Length property, |
||
GetLength(new int[] { 1, 2, 3 }); // and so does an array, |
GetLength(new int[] { 1, 2, 3 }); // and so does an array, |
||
GetLength(42); // but not an integer - an exception will be thrown |
GetLength(42); // but not an integer - an exception will be thrown in GetLength method at run-time |
||
</syntaxhighlight> |
|||
</source> |
|||
Dynamic method calls are triggered by a value of type |
Dynamic method calls are triggered by a value of type <code>dynamic</code> as any implicit or explicit parameter (and not just a receiver). For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
void Print(dynamic obj) |
void Print(dynamic obj) |
||
{ |
{ |
||
Line 40: | Line 41: | ||
Print(123); // ends up calling WriteLine(int) |
Print(123); // ends up calling WriteLine(int) |
||
Print("abc"); // ends up calling WriteLine(string) |
Print("abc"); // ends up calling WriteLine(string) |
||
</syntaxhighlight> |
|||
</source> |
|||
Dynamic lookup is performed using three distinct mechanisms: COM [[IDispatch]] for COM objects, <code> |
Dynamic lookup is performed using three distinct mechanisms: COM [[IDispatch]] for COM objects, <code>IDynamicMetaObjectProvider</code> DLR interface for objects implementing that interface, and [[Reflection (computer science)|reflection]] for all other objects. Any C# class can therefore intercept dynamic calls on its instances by implementing <code>IDynamicMetaObjectProvider</code>. |
||
In case of dynamic method and indexer calls, overload resolution happens at run-time according to the actual types of the values passed as arguments, but otherwise according to the usual C# overloading resolution rules. Furthermore, in cases where the receiver in a dynamic call is not itself dynamic, run-time overload resolution will only consider the methods that are exposed on the declared compile-time type of the receiver. For example: |
In case of dynamic method and indexer calls, overload resolution happens at run-time according to the actual types of the values passed as arguments, but otherwise according to the usual C# overloading resolution rules. Furthermore, in cases where the receiver in a dynamic call is not itself dynamic, run-time overload resolution will only consider the methods that are exposed on the declared compile-time type of the receiver. For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
class Base |
class Base |
||
{ |
{ |
||
Line 62: | Line 63: | ||
dynamic b1 = b; |
dynamic b1 = b; |
||
b1.Foo(x); // picks Derived.Foo(int) |
b1.Foo(x); // picks Derived.Foo(int) |
||
</syntaxhighlight> |
|||
</source> |
|||
Any value returned from a dynamic member access is itself of type <code>dynamic</code>. Values of type <code>dynamic</code> are implicitly convertible both from and to any other type. In the code sample above |
Any value returned from a dynamic member access is itself of type <code>dynamic</code>. Values of type <code>dynamic</code> are implicitly convertible both from and to any other type. In the code sample above this permits <code>GetLength</code> function to treat the value returned by a call to <code>Length</code> as an integer without any explicit cast. At run time the actual value will be converted to the requested type. |
||
=== Covariant and contravariant generic type parameters === |
=== Covariant and contravariant generic type parameters === |
||
[[Generic programming|Generic]] interfaces and delegates can have their type parameters marked as [[Covariance and contravariance (computer science)|covariant |
[[Generic programming|Generic]] interfaces and delegates can have their type parameters marked as [[Covariance and contravariance (computer science)|covariant or contravariant]] using keywords <code>out</code> and <code>in</code> respectively. These declarations are then respected for type conversions, both implicit and explicit, and both compile time and run time. For example, the existing interface <code>IEnumerable<T></code> has been redefined as follows: |
||
< |
<syntaxhighlight lang="csharp"> |
||
interface IEnumerable<out T> |
interface IEnumerable<out T> |
||
{ |
{ |
||
IEnumerator<T> GetEnumerator(); |
IEnumerator<T> GetEnumerator(); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Therefore, any class that implements <code>IEnumerable<Derived></code> for some class <code>Derived</code> is also considered to be compatible with <code>IEnumerable<Base></code> for all classes and interfaces <code>Base</code> that <code>Derived</code> extends, directly |
Therefore, any class that implements <code>IEnumerable<Derived></code> for some class <code>Derived</code> is also considered to be compatible with <code>IEnumerable<Base></code> for all classes and interfaces <code>Base</code> that <code>Derived</code> extends, directly or indirectly. In practice, it makes it possible to write code such as: |
||
< |
<syntaxhighlight lang="csharp"> |
||
void PrintAll(IEnumerable<object> objects) |
void PrintAll(IEnumerable<object> objects) |
||
{ |
{ |
||
Line 90: | Line 91: | ||
IEnumerable<string> strings = new List<string>(); |
IEnumerable<string> strings = new List<string>(); |
||
PrintAll(strings); // IEnumerable<string> is implicitly converted to IEnumerable<object> |
PrintAll(strings); // IEnumerable<string> is implicitly converted to IEnumerable<object> |
||
</syntaxhighlight> |
|||
</source> |
|||
For contravariance, the existing interface <code>IComparer<T></code> has been redefined as follows: |
For contravariance, the existing interface <code>IComparer<T></code> has been redefined as follows: |
||
< |
<syntaxhighlight lang="csharp"> |
||
public interface IComparer<in T> |
public interface IComparer<in T> |
||
{ |
{ |
||
int Compare(T x, T y); |
int Compare(T x, T y); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Therefore, any class that implements <code>IComparer<Base></code> for some class <code>Base</code> is also considered to be compatible with <code>IComparer<Derived></code> for all classes and interfaces <code>Derived</code> that are extended from <code>Base</code>. It makes it possible to write code such as: |
Therefore, any class that implements <code>IComparer<Base></code> for some class <code>Base</code> is also considered to be compatible with <code>IComparer<Derived></code> for all classes and interfaces <code>Derived</code> that are extended from <code>Base</code>. It makes it possible to write code such as: |
||
< |
<syntaxhighlight lang="csharp"> |
||
IComparer<object> objectComparer = GetComparer(); |
IComparer<object> objectComparer = GetComparer(); |
||
IComparer<string> stringComparer = objectComparer; |
IComparer<string> stringComparer = objectComparer; |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Optional ref |
=== Optional ref keyword when using COM === |
||
The ref keyword for callers of methods is now optional when calling into methods supplied by COM interfaces. Given a COM method with the signature |
The <code>ref</code> keyword for callers of methods is now optional when calling into methods supplied by [[Component Object Model|COM]] interfaces. Given a COM method with the signature |
||
< |
<syntaxhighlight lang="csharp">void Increment(ref int x);</syntaxhighlight> |
||
the invocation can now be written as either |
the invocation can now be written as either |
||
< |
<syntaxhighlight lang="csharp"> |
||
Increment(0); // no need for "ref" or a place holder variable any more |
Increment(0); // no need for "ref" or a place holder variable any more |
||
</syntaxhighlight> |
|||
</source> |
|||
or |
or |
||
< |
<syntaxhighlight lang="csharp"> |
||
int x = 0; |
int x = 0; |
||
Increment(ref x); |
Increment(ref x); |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Optional parameters and named arguments === |
=== Optional parameters and named arguments === |
||
C# 4.0 introduces optional parameters with default values as seen in C++. For example: |
C# 4.0 introduces optional parameters with default values as seen in [[Visual Basic .NET|Visual Basic]] and [[C++]]. For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
void Increment(ref int x, int dx = 1) |
void Increment(ref int x, int dx = 1) |
||
{ |
{ |
||
Line 129: | Line 130: | ||
int x = 0; |
int x = 0; |
||
Increment(ref x); // dx takes the default value of 1 |
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 |
Increment(ref x, 2); // dx takes the value 2, after the method returns x == 3 |
||
</syntaxhighlight> |
|||
</source> |
|||
In addition, to complement optional parameters, it is possible |
In addition, to complement optional parameters, it is possible explicitly to specify parameter names in method calls, allowing the programmer selectively to pass any subset of optional parameters for a method. The only restriction is that [[named parameter]]s must be placed after the unnamed parameters. Parameter names can be specified for both optional and required parameters, and can be used to improve readability or arbitrarily to reorder arguments in a call. For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
Stream OpenFile(string name, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) { ... } |
Stream OpenFile(string name, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) { ... } |
||
Line 143: | Line 144: | ||
OpenFile(name: "file.txt", access: FileAccess.Read, mode: FileMode.Create); // name all parameters for extra readability, |
OpenFile(name: "file.txt", access: FileAccess.Read, mode: FileMode.Create); // name all parameters for extra readability, |
||
// and use order different from method declaration |
// and use order different from method declaration |
||
</syntaxhighlight> |
|||
</source> |
|||
Optional parameters make interoperating with COM easier. Previously, C# had to pass in every parameter in the method of the COM component, even those that are optional. For example: |
Optional parameters make interoperating with COM easier. Previously, C# had to pass in every parameter in the method of the COM component, even those that are optional. For example: |
||
< |
<syntaxhighlight lang="csharp"> |
||
object fileName = "Test.docx"; |
object fileName = "Test.docx"; |
||
object missing = System.Reflection.Missing.Value; |
object missing = System.Reflection.Missing.Value; |
||
Line 157: | Line 158: | ||
ref missing, ref missing, ref missing, |
ref missing, ref missing, ref missing, |
||
ref missing, ref missing, ref missing); |
ref missing, ref missing, ref missing); |
||
</syntaxhighlight> |
|||
</source> |
|||
With support for optional parameters, the code can be shortened as |
With support for optional parameters, the code can be shortened as |
||
< |
<syntaxhighlight lang="csharp"> |
||
doc.SaveAs(ref fileName); |
doc.SaveAs(ref fileName); |
||
</syntaxhighlight> |
|||
</source> |
|||
Which, due to the now optional <code>ref</code> keyword when using COM, can further be shortened as |
|||
<syntaxhighlight lang="csharp"> |
|||
doc.SaveAs(fileName); |
|||
</syntaxhighlight> |
|||
=== Indexed properties === |
=== Indexed properties === |
||
Indexed properties (and default properties) of COM objects are now |
Indexed properties (and default properties) of COM objects are now recognized, but C# objects still do not support them. |
||
== References == |
== References == |
||
Line 172: | Line 178: | ||
==External links== |
==External links== |
||
*{{cite web |
|||
[http://code.msdn.microsoft.com/csharpfuture/Release/ProjectReleases.aspx?ReleaseId=1686 C# Future (Microsoft MSDN) with link to "New Features in C# 4.0" document] |
|||
|url=https://learn.microsoft.com/en-us/archive/msdn-magazine/2010/july/csharp-4-0-new-csharp-features-in-the-net-framework-4 |
|||
|title=C# 4.0 - New C# Features in the .NET Framework 4 |
|||
{{s-start}} |
|||
|first=Chris |
|||
{{s-bef | before = [[C Sharp 3.0|C# 3.0]]}} |
|||
|last=Burrows |
|||
{{s-ttl | title=Versions of [[C Sharp (programming language)|C#]]}} |
|||
|year=2010 |
|||
{{s-inc|recent}} |
|||
|publisher=[[Microsoft]] |
|||
{{end}} |
|||
|accessdate=2023-07-14 |
|||
}} |
|||
* [http://go.microsoft.com/fwlink/?LinkId=188622 C# 4.0 Language Specification] |
|||
[[Category:C Sharp programming language family]] |
[[Category:C Sharp programming language family]] |
Latest revision as of 05:08, 14 July 2023
C# 4.0 is a version of the C# programming language that was released on April 11, 2010. Microsoft released the 4.0 runtime and development environment Visual Studio 2010.[1] The major focus of C# 4.0 is interoperability with partially or fully dynamically typed languages and frameworks, such as the Dynamic Language Runtime and COM.
Features[edit]
The following new features were added in C# 4.0.[2]
Dynamic member lookup[edit]
A new pseudo-type dynamic
is introduced into the C# type system. It is treated as System.Object
, but in addition, any member access (method call, field, property, or indexer access, or a delegate invocation) or application of an operator on a value of such type is permitted without any type checking, and its resolution is postponed until run-time. This is known as duck typing. For example:
// 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 method calls are triggered by a value of type dynamic
as any implicit or explicit parameter (and not just a receiver). For example:
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)
Dynamic lookup is performed using three distinct mechanisms: COM IDispatch for COM objects, IDynamicMetaObjectProvider
DLR interface for objects implementing that interface, and reflection for all other objects. Any C# class can therefore intercept dynamic calls on its instances by implementing IDynamicMetaObjectProvider
.
In case of dynamic method and indexer calls, overload resolution happens at run-time according to the actual types of the values passed as arguments, but otherwise according to the usual C# overloading resolution rules. Furthermore, in cases where the receiver in a dynamic call is not itself dynamic, run-time overload resolution will only consider the methods that are exposed on the declared compile-time type of the receiver. For example:
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)
Any value returned from a dynamic member access is itself of type dynamic
. Values of type dynamic
are implicitly convertible both from and to any other type. In the code sample above this permits GetLength
function to treat the value returned by a call to Length
as an integer without any explicit cast. At run time the actual value will be converted to the requested type.
Covariant and contravariant generic type parameters[edit]
Generic interfaces and delegates can have their type parameters marked as covariant or contravariant using keywords out
and in
respectively. These declarations are then respected for type conversions, both implicit and explicit, and both compile time and run time. For example, the existing interface IEnumerable<T>
has been redefined as follows:
interface IEnumerable<out T>
{
IEnumerator<T> GetEnumerator();
}
Therefore, any class that implements IEnumerable<Derived>
for some class Derived
is also considered to be compatible with IEnumerable<Base>
for all classes and interfaces Base
that Derived
extends, directly or indirectly. In practice, it makes it possible to write code such as:
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>
For contravariance, the existing interface IComparer<T>
has been redefined as follows:
public interface IComparer<in T>
{
int Compare(T x, T y);
}
Therefore, any class that implements IComparer<Base>
for some class Base
is also considered to be compatible with IComparer<Derived>
for all classes and interfaces Derived
that are extended from Base
. It makes it possible to write code such as:
IComparer<object> objectComparer = GetComparer();
IComparer<string> stringComparer = objectComparer;
Optional ref keyword when using COM[edit]
The ref
keyword for callers of methods is now optional when calling into methods supplied by COM interfaces. Given a COM method with the signature
void Increment(ref int x);
the invocation can now be written as either
Increment(0); // no need for "ref" or a place holder variable any more
or
int x = 0;
Increment(ref x);
Optional parameters and named arguments[edit]
C# 4.0 introduces optional parameters with default values as seen in Visual Basic and C++. For example:
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
In addition, to complement optional parameters, it is possible explicitly to specify parameter names in method calls, allowing the programmer selectively to pass any subset of optional parameters for a method. The only restriction is that named parameters must be placed after the unnamed parameters. Parameter names can be specified for both optional and required parameters, and can be used to improve readability or arbitrarily to reorder arguments in a call. For example:
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
Optional parameters make interoperating with COM easier. Previously, C# had to pass in every parameter in the method of the COM component, even those that are optional. For example:
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);
With support for optional parameters, the code can be shortened as
doc.SaveAs(ref fileName);
Which, due to the now optional ref
keyword when using COM, can further be shortened as
doc.SaveAs(fileName);
Indexed properties[edit]
Indexed properties (and default properties) of COM objects are now recognized, but C# objects still do not support them.
References[edit]
- ^ "Microsoft Visual Studio 2010 First Look". Microsoft.
- ^ Burrows, Chris (2010). "C# 4.0 - New C# Features in the .NET Framework 4". Microsoft. Retrieved 2023-07-14.
External links[edit]
- Burrows, Chris (2010). "C# 4.0 - New C# Features in the .NET Framework 4". Microsoft. Retrieved 2023-07-14.
- C# 4.0 Language Specification