C Sharp syntax
This article describes the syntax of the C# programming language.[] The features described are compatible with.NET Framework and Mono.
Basics
Identifier
An identifier is the name of an element in the code. There are certain standard naming conventions to follow when selecting names for elements.An identifier can:
- start with an underscore: _
- contain an underscore: _
- contain a digit: 0123456789
- contain both upper case and lower case Unicode letters. Case is sensitive
- begin with an @ sign.
- start with a digit
- start with a symbol, unless it is a keyword
- contain more than 511 characters
- contain @ sign after its first character
Keywords
Using a keyword as an identifier:
string @out; // @out is an ordinary identifier, distinct from the 'out' keyword,
// which retains its special meaning
Literals
Digit separators
The underscore symbol separates digits in number values for readability purposes. The compiler ignores these underscores.int bin = 0b1101_0010_1011_0100;
int hex = 0x2F_BB_4A_F1;
int dec = 1_000_500_954;
double real = 1_500.200_2e-1_000;
Generally, it may be put only between digit characters. It cannot be put at the beginning or the end of the value, next to the decimal in floating point values, next to the exponent character and next to the type specifier.
Variables
are identifiers associated with values. They are declared by writing the variable's type and name, and are optionally initialized in the same statement.Declare
int myInt; // Declaring an uninitialized variable called 'myInt', of type 'int'
Assigning
int myInt; // Declaring an uninitialized variable
myInt = 35; // Assigning the variable a value
Initialize
int myInt = 35; // Declaring and initializing the variable
Multiple variables of the same type can be declared and initialized in one statement.
int a, b; // Declaring multiple variables of the same type
int a = 2, b = 3; // Declaring and initializing multiple variables of the same type
Local variable type inference
C# 3.0 introduced type inference, allowing the type specifier of a variable declaration to be replaced by the keyword, if its actual type can be statically determined from the initializer. This reduces repetition, especially for types with multiple generic [|type-parameters], and adheres more closely to the DRY principle.var myChars = new char ; // or char myChars = new char ;
var myNums = new List
See also
- Type inference
Constants
const double PI = 3.14;
This shows both uses of the keyword.
class Foo
Code blocks
Curly braces are used to signify a code block and a new scope. Class members and the body of a method are examples of what can live inside these braces in various contexts.Inside of method bodies you can use the braces to create new scopes like so:
void doSomething
Program structure
A C# application consists of classes and their members. Classes and other types exist in namespaces but can also be nested inside other classes.method
Whether it is a console or a graphical interface application, the program must have an entry point of some sort. The entry point of the C# application is the method. There can only be one, and it is a static method in a class. The method usually returns and is passed command-line arguments as an array of strings.static void Main
// OR Main method can be defined without parameters.
static void Main
A method is also allowed to return an integer value if specified.
static int Main
Namespaces
Namespaces are a part of a type name and they are used to group and/or distinguish named entities from other ones.System.IO.DirectoryInfo // DirectoryInfo is in the System.IO-namespace
A namespace is defined like this:
namespace FooNamespace
directive
The directive loads a specific namespace from a referenced assembly. It is usually placed in the top of a code file but it can be placed elsewhere if wanted, e.g. inside classes.using System;
using System.Collections;
The directive can also be used to define another name for an existing namespace or type. This is sometimes useful when names are too long and less readable.
using Net = System.Net;
using DirInfo = System.IO.DirectoryInfo;
Operators
Operator overloading
Some of the existing operators can be overloaded by writing an overload method.public static Foo operator+
These are the overloadable operators:
Operators | |
,,,,,,, | Unary operators |
,,,,,,,,, | Binary operators |
, != ,,, <= , >= | Comparison operators, must be overloaded in pairs |
- Assignment operators are combinations of a binary operator and the assignment operator and will be evaluated using the ordinary operators, which can be overloaded.
- Cast operators cannot be overloaded, but you can define conversion operators.
- Array indexing operator is not overloadable, but you can define new indexers.
- Operator overloading
Conversion operators
Implicit conversion operator
class Foo
// Implicit conversion
Foo foo = 2;
Explicit conversion operator
class Foo
// Explicit conversion
Foo foo = 2;
operator
The operator will attempt to do a silent cast to a given type. It will return the object as the new type if possible, and otherwise will return null.Stream stream = File.Open;
FileStream fstream = stream as FileStream; // Will return an object.
String str = stream as String; // Will return null.
Null coalesce operator
The following:return ifNotNullValue ?? otherwiseValue;
is shorthand for:
return ifNotNullValue != null ? ifNotNullValue : otherwiseValue;
Meaning that if the content of variable is not null, that content will be returned, otherwise the content of variable is returned.
C# 8.0 introduces null-coalescing assignment, such that
variable ??= otherwiseValue;
is equivalent to
if variable = otherwiseValue;
Control structures
C# inherits most of the control structures of C/C++ and also adds new ones like the statement.Conditional structures
These structures control the flow of the program through given conditions.statement
The statement is entered when the given condition is true. Single-line case statements do not require block braces although it is mostly preferred by convention.Simple one-line statement:
if ... ;
Multi-line with else-block :
if
...
else
...
Recommended coding conventions for an if-statement.
if
else if
else
statement
The construct serves as a filter for different values. Each value leads to a "case". It is not allowed to fall through case sections and therefore the keyword is typically used to end a case. An unconditional in a case section can also be used to end a case. See also how statement can be used to fall through from one case to the next. Many cases may lead to the same code though. The default case handles all the other cases not handled by the construct.switch
Iteration structures
Iteration statements are statements that are repeatedly executed when a given condition is evaluated as true.loop
while
loop
do
while ;
loop
The loop consists of three parts: declaration, condition and counter expression. Any of them can be left out as they are optional.for
Is equivalent to this code represented with a statement, except here the variable is not local to the loop.
int i = 0;
while
loop
The statement is derived from the statement and makes use of a certain pattern described in C#'s language specification in order to obtain and use an enumerator of elements to iterate over.Each item in the given collection will be returned and reachable in the context of the code block. When the block has been executed the next item will be returned until there are no items remaining.
foreach
Jump statements
Jump statements are inherited from C/C++ and ultimately assembly languages through it. They simply represent the jump-instructions of an assembly language that controls the flow of a program.Labels and statement
Labels are given points in code that can be jumped to by using the statement.start:
.......
goto start;
Note that the label need not be positioned after the statement; it may be before it in the source file.
The statement can be used in statements to jump from one case to another or to fall through from one case to the next.
switch
statement
The statement breaks out of the closest loop or statement. Execution continues in the statement after the terminated statement, if any.int e = 10;
for
statement
The statement discontinues the current iteration of the current control statement and begins the next iteration.int ch;
while ) != -1)
The loop in the code above reads characters by calling, skipping the statements in the body of the loop if the characters are spaces.
Exception handling
Runtime exception handling method in C# is inherited from Java and C++.The base class library has a class called from which all other exception classes are derived. An -object contains all the information about a specific exception and also the inner exceptions that were caused.
Programmers may define their own exceptions by deriving from the class.
An exception can be thrown this way:
throw new NotImplementedException;
statements
Exceptions are managed within blocks.try
catch
finally
The statements within the block are executed, and if any of them throws an exception, execution of the block is discontinued and the exception is handled by the block. There may be multiple blocks, in which case the first block with an exception variable whose type matches the type of the thrown exception is executed.
If no block matches the type of the thrown exception, the execution of the outer block containing the statement is discontinued, and the exception is passed up and outside the containing block or method. The exception is propagated upwards through the call stack until a matching block is found within one of the currently active methods. If the exception propagates all the way up to the top-most method without a matching block being found, the entire program is terminated and a textual description of the exception is written to the standard output stream.
The statements within the block are always executed after the and blocks, whether or not an exception was thrown. Such blocks are useful for providing clean-up code.
Either a block, a block, or both, must follow the block.
Types
C# is a statically typed language like C and C++. That means that every variable and constant gets a fixed type when it is being declared. There are two kinds of types: value types and reference types.Value types
Instances of value types reside on the stack, i.e. they are bound to their variables. If you declare a variable for a value type the memory gets allocated directly. If the variable gets out of scope the object is destroyed with it.Structures
Structures are more commonly known as structs. Structs are user-defined value types that are declared using the keyword. They are very similar to classes but are more suitable for lightweight types. Some important syntactical differences between a and a are presented later in this article.struct Foo
The primitive data types are all structs.
Pre-defined types
These are the primitive datatypes.Note: is not a struct and is not a primitive type.
Enumerations
Enumerated types are named values representing integer values.enum Season
variables are initialized by default to zero. They can be assigned or initialized to the named values defined by the enumeration type.
Season season;
season = Season.Spring;
type variables are integer values. Addition and subtraction between variables of the same type is allowed without any specific cast but multiplication and division is somewhat more risky and requires an explicit cast. Casts are also required for converting variables to and from integer types. However, the cast will not throw an exception if the value is not specified by the type definition.
season = 2; // cast 2 to an enum-value of type Season.
season = season + 1; // Adds 1 to the value.
season = season + season2; // Adding the values of two enum variables.
int value = season; // Casting enum-value to integer value.
season++; // Season.Spring becomes Season.Summer.
season--; // Season.Summer becomes Season.Spring.
Values can be combined using the bitwise-OR operator.
Color myColors = Color.Green | Color.Yellow | Color.Blue;
See also
- Enumeration
Arrays
An array in C# is what would be called a dynamic array in C++.
int numbers = new int;
numbers = 2;
numbers = 5;
int x = numbers;
Initializers
Array initializers provide convenient syntax for initialization of arrays.// Long syntax
int numbers = new int;
// Short syntax
int numbers2 = ;
// Inferred syntax
var numbers3 = new ;
Multi-dimensional arrays
Arrays can have more than one dimension, for example 2 dimensions to represent a grid.int numbers = new int;
numbers = 2;
int numbers2 = new int ;
See also
- Jagged array
Classes
class
The class, or simply, represents an immutable sequence of unicode characters.Actions performed on a string will always return a new string.
string text = "Hello World!";
string substr = text.Substring;
string parts = text.Split;
The class can be used when a mutable "string" is wanted.
StringBuilder sb = new StringBuilder;
sb.Append;
sb.Append;
sb.AppendLine;
Interface
Interfaces are data structures that contain member definitions with no actual implementation. A variable of an interface type is a reference to an instance of a class which implements this interface. See #Interfaces.Delegates
C# provides type-safe object-oriented function pointers in the form of delegates.class Program
Initializing the delegate with an anonymous method.
Initializing the delegate with lambda expression.
Events
Events are pointers that can point to multiple methods. More exactly they bind method pointers to one identifier. This can therefore be seen as an extension to delegates. They are typically used as triggers in UI development. The form used in C# and the rest of the Common Language Infrastructure is based on that in the classic Visual Basic.delegate void MouseEventHandler;
public class Button : System.Windows.Controls.Control
An event requires an accompanied event handler that is made from a special delegate that in a platform specific library like in Windows Presentation Foundation and Windows Forms usually takes two parameters: sender and the event arguments. The type of the event argument-object derive from the EventArgs class that is a part of the CLI base library.
Once declared in its class the only way of invoking the event is from inside of the owner. A listener method may be implemented outside to be triggered when the event is fired.
public class MainWindow : System.Windows.Controls.Window
Custom event implementation is also possible:
private EventHandler clickHandles = => ;
public event EventHandler Click
See also
- Event-driven programming
Nullable types
int? n = 2;
n = null;
Console.WriteLine;
In reality this is the same as using the struct.
Nullable
n = null;
Console.WriteLine;
Pointers
C# has and allows pointers to selected types in unsafe context: methods and codeblock marked. These are syntactically the same as pointers in C and C++. However, runtime-checking is disabled inside blocks.static void Main
Structs are required only to be pure structs with no members of a managed reference type, e.g. a string or any other class.
public struct MyStruct
public struct MyContainerStruct
In use:
MyContainerStruct x;
MyContainerStruct* ptr = &x;
byte value = ptr->Byte;
See also
- Pointer
Dynamic
This feature takes advantage of the Dynamic Language Runtime and has been designed specifically with the goal of interoping with dynamically typed languages like IronPython and IronRuby.
Dynamic-support also eases interop with COM objects.
dynamic x = new Foo;
x.DoSomething; // Will compile and resolved at runtime. An exception will be thrown if invalid.
Anonymous types
Anonymous types are nameless classes that are generated by the compiler. They are only consumable and yet very useful in a scenario like where you have a LINQ query which returns an object on and you just want to return some specific values. Then you can define an anonymous type containing auto-generated read-only fields for the values.When instantiating another anonymous type declaration with the same signature the type is automatically inferred by the compiler.
var carl = new ; // Name of the type is only known by the compiler.
var mary = new ; // Same type as the expression above
Boxing and unboxing
Boxing is the operation of converting a value of a value type into a value of a corresponding reference type. Boxing in C# is implicit.Unboxing is the operation of converting a value of a reference type into a value of a value type. Unboxing in C# requires an explicit type cast.
Example:
int foo = 42; // Value type.
object bar = foo; // foo is boxed to bar.
int foo2 = bar; // Unboxed back to value type.
Object-oriented programming (OOP)
C# has direct support for object-oriented programming.Objects
An object is created with the type as a template and is called an instance of that particular type.In C#, objects are either references or values. No further syntactical distinction is made between those in code.
class
All types, even value types in their boxed form, implicitly inherit from the class, the ultimate base class of all objects. This class contains the most common methods shared by all objects. Some of these are and can be overridden.Classes inherit either directly or indirectly through another base class.
Members
Some of the members of the class:
- - Supports comparisons between objects.
- - Performs cleanup operations before an object is automatically reclaimed.
- - Gets the number corresponding to the value of the object to support the use of a hash table.
- - Gets the Type of the current instance.
- - Creates a human-readable text string that describes an instance of the class. Usually it returns the name of the type.
Classes
See also
- Class
- Structure
Differences between classes and structs
Structures require some more work than classes. For example, you need to explicitly create a default constructor which takes no arguments to initialize the struct and its members. The compiler will create a default one for classes. All fields and properties of a struct must have been initialized before an instance is created. Structs do not have finalizers and cannot inherit from another class like classes do. However, they inherit from, that inherits from. Structs are more suitable for smaller constructs of data.
This is a short summary of the differences:
Declaration
A class is declared like this:class Foo
Partial class
A partial class is a class declaration whose code is divided into separate files. The different parts of a partial class must be marked with keyword.// File1.cs
partial class Foo
// File2.cs
partial class Foo
Initialization
Before you can use the members of the class you need to initialize the variable with a reference to an object. To create it you call the appropriate constructor using the keyword. It has the same name as the class.Foo foo = new Foo;
For structs it is optional to explicitly call a constructor because the default one is called automatically. You just need to declare it and it gets initialized with standard values.
Object initializers
Provides a more convenient way of initializing public fields and properties of an object. Constructor calls are optional when there is a default constructor.Person person = new Person ;
// Equal to
Person person = new Person;
person.Name = "John Doe";
person.Age = 39;
Collection initializers
Collection initializers give an array-like syntax for initializing collections. The compiler will simply generate calls to the Add-method. This works for classes that implement the interface.List
// Equal to
List
list.Add;
list.Add;
list.Add;
list.Add;
Accessing members
Members of an instance and static members of a class are accessed using the operator.Accessing an instance member
Instance members can be accessed through the name of a variable.
string foo = "Hello";
string fooUpper = foo.ToUpper;
Accessing a static class member
Static members are accessed by using the name of the class or other type.
int r = String.Compare;
Accessing a member through a pointer
In unsafe code, members of a value referenced by a pointer are accessed with the operator just like in C and C++.
POINT p;
p.X = 2;
p.Y = 6;
POINT* ptr = &p;
ptr->Y = 4;
Modifiers
Modifiers are keywords used to modify declarations of types and type members. Most notably there is a sub-group containing the access modifiers.Class modifiers
- - Specifies that a class only serves as a base class. It must be implemented in an inheriting class.
- - Specifies that a class cannot be inherited.
Class member modifiers
- - Specifies that a variable is a constant value that has to be initialized when it gets declared.
- - Declares an event.
- - Specifies that a method signature without a body uses a DLL-import.
- - Specifies that a method or property declaration is an override of a virtual member or an implementation of a member of an abstract class.
- - Declares a field that can only be assigned values as part of the declaration or in a constructor in the same class.
- - Specifies an unsafe context, which allows the use of pointers.
- - Specifies that a method or property declaration can be overridden by a derived class.
- - Specifies a field which may be modified by an external process and prevents an optimizing compiler from modifying the use of the field.
modifier
public class Foo
// Calling the class method.
Foo.Something;
Access modifiers
The access modifiers, or inheritance modifiers, set the accessibility of classes, methods, and other members. Something marked can be reached from anywhere. members can only be accessed from inside of the class they are declared in and will be hidden when inherited. Members with the modifier will be, but accessible when inherited. classes and members will only be accessible from the inside of the declaring assembly.Classes and structs are implicitly and members are implicitly if they do not have an access modifier.
public class Foo
This table defines where the access modifiers can be used.
Unnested types | Members | |
yes | yes | |
no | yes | |
no | yes | |
yes | yes | |
no | yes | |
no | yes |
Constructors
A constructor is a special method that is called automatically when an object is created. Its purpose is to initialize the members of the object. Constructors have the same name as the class and do not return anything. They may take parameters like any other method.class Foo
Constructors can be,, or.
See also
- Constructor
Destructor
The syntax is similar to the one of constructors. The difference is that the name is preceded by a ~ and it cannot contain any parameters. There cannot be more than one destructor.
class Foo
Finalizers are always.
See also
- Destructor
Methods
class Foo
A method is called using notation on a specific variable, or as in the case of static methods, the name of a type.
Foo foo = new Foo;
int r = foo.Bar;
Console.WriteLine;
See also
- Method
and parameters
void PassRef
int Z;
PassRef;
void PassOut
int Q;
PassOut;
Optional parameters
C# 4.0 introduces optional parameters with default values as seen in C++. For example:void Increment
int x = 0;
Increment; // dx takes the default value of 1
Increment; // dx takes the value 2
In addition, to complement optional parameters, it is possible to explicitly specify parameter names in method calls, allowing to selectively pass any given 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 reorder arguments in a call. For example:
Stream OpenFile
OpenFile; // use default values for both "mode" and "access"
OpenFile; // use default value for "access"
OpenFile; // use default value for "mode"
OpenFile;
// 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;
console.writeline;
With support for optional parameters, the code can be shortened as
doc.SaveAs;
static extern double Pow;
Fields
Fields, or class variables, can be declared inside the class body to store data.class Foo
Fields can be initialized directly when declared.
class Foo
Modifiers for fields:
- - Makes the field a constant.
- - Makes the field private.
- - Makes the field protected.
- - Makes the field public.
- - Allows the field to be initialized only once in a constructor.
- - Makes the field a static member.
Properties
class Person
// Using a property
Person person = new Person;
person.Name = "Robert";
Modifiers for properties:
- - Makes the property private.
- - Makes the property protected.
- - Makes the property public.
- - Makes the property a static member.
- - Makes the accessor private.
- - Makes the accessor protected.
- - Makes the accessor public.
Automatic properties
A feature of C# 3.0 is auto-implemented properties. You define accessors without bodies and the compiler will generate a backing field and the necessary code for the accessors.public double Width
Indexers
Indexers add array-like indexing capabilities to objects. They are implemented in a way similar to properties.class IntList
// Using an indexer
IntList list = new IntList;
list = 2;
Inheritance
Classes in C# may only inherit from one class. A class may derive from any class that is not marked as.class A
class B : A
See also
- Inheritance
The implementation is chosen by the actual type of the object and not the type of the variable.
class Operation
class NewOperation : Operation
class Operation
class NewOperation : Operation
This demonstrates the case:
NewOperation operation = new NewOperation;
// Will call "double Do" in NewOperation
double d = operation.Do;
Operation operation_ = operation;
// Will call "int Do" in Operation
int i = operation_.Do;
There may be abstract members too. Abstract members are members of abstract classes that do not have any implementation. They must be overridden by the class that inherits the member.
abstract class Mammal
class Human : Mammal
internal sealed class _FOO
Interfaces
Interfaces are data structures that contain member definitions and not actual implementation. They are useful when you want to define a contract between members in different types that have different implementations. You can declare definitions for methods, properties, and indexers. Interface members are implicitly public. An interface can either be implicitly or explicitly implemented.interface IBinaryOperation
Implementing an interface
An interface is implemented by a class or extended by another interface in the same way you derive a class from another class using the notation.Implicit implementation
When implicitly implementing an interface the members of the interface have to be.
public class Adder : IBinaryOperation
public class Multiplier : IBinaryOperation
In use:
IBinaryOperation op = null;
double result;
// Adder implements the interface IBinaryOperation.
op = new Adder;
op.A = 2;
op.B = 3;
result = op.GetResult; // 5
// Multiplier also implements the interface.
op = new Multiplier;
op.A = 5;
op.B = 4;
result = op.GetResult; // 20
Explicit implementation
You can also explicitly implement members. The members of the interface that are explicitly implemented by a class are accessible only when the object is handled as the interface type.
public class Adder : IBinaryOperation
In use:
Adder add = new Adder;
// These members are not accessible:
// add.A = 2;
// add.B = 3;
// double result = add.GetResult;
// Cast to the interface type to access them:
IBinaryOperation add2 = add;
add2.A = 2;
add2.B = 3;
double result = add2.GetResult;
Note: The properties in the class that extends are auto-implemented by the compiler and a backing field is automatically added.
Extending multiple interfaces
Interfaces and classes are allowed to extend multiple interfaces.
class MyClass : IInterfaceA, IInterfaceB
Here is an interface that extends two interfaces.
interface IInterfaceC : IInterfaceA, IInterfaceB
Interfaces vs. abstract classes
Interfaces and abstract classes are similar. The following describes some important differences:- An abstract class may have member variables as well as non-abstract methods or properties. An interface cannot.
- A class or abstract class can only inherit from one class or abstract class.
- A class or abstract class may implement one or more interfaces.
- An interface can only extend other interfaces.
- An abstract class may have non-public methods and properties. An interface can only have public members.
- An abstract class may have constants, static methods and static members. An interface cannot.
- An abstract class may have constructors. An interface cannot.
Generics
// Declare the generic class.
public class GenericList
class TestGenericList
When compared with C++ templates, C# generics can provide enhanced safety, but also have somewhat limited capabilities. For example, it is not possible to call arithmetic operators on a C# generic type. Unlike C++ templates,.NET parameterized types are instantiated at runtime rather than by the compiler; hence they can be cross-language whereas C++ templates cannot. They support some features not supported directly by C++ templates such as type constraints on generic parameters by use of interfaces. On the other hand, C# does not support non-type generic parameters.
Unlike generics in Java,.NET generics use reification to make parameterized types first-class objects in the Common Language Infrastructure Virtual Machine, which allows for optimizations and preservation of the type information.
Using generics
Generic classes
Classes and structs can be generic.public class List
List
list.Add;
list.Add;
Generic interfaces
interface IEnumerable
Generic delegates
delegate R Func
Generic methods
public static T CombineArrays
string a = new string ;
string b = new string ;
string c = CombineArrays;
double da = new double ;
double db = new double ;
double dc = CombineArrays;
// c is a string array containing
// dc is a double array containing
Type-parameters
Type-parameters are names used in place of concrete types when defining a new generic. They may be associated with classes or methods by placing the type parameter in angle brackets. When instantiating a generic, you can then substitute a concrete type for the type-parameter you gave in its declaration. Type parameters may be constrained by use of the keyword and a constraint specification, any of the six comma separated constraints may be used:Constraint | Explanation |
type parameter must be a value type | |
type parameter must be a reference type | |
type parameter must have a constructor with no parameters | |
type parameter must inherit from | |
type parameter must be, or must implement this interface | |
naked type parameter constraint |
Covariance and contravariance
Generic interfaces and delegates can have their type parameters marked as covariant or contravariant, using keywords and, 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 has been redefined as follows:interface IEnumerable
Therefore, any class that implements for some class is also considered to be compatible with for all classes and interfaces that extends, directly, or indirectly. In practice, it makes it possible to write code such as:
void PrintAll
IEnumerable
PrintAll; // IEnumerable
For contravariance, the existing interface has been redefined as follows:
public interface IComparer
Therefore, any class that implements for some class is also considered to be compatible with for all classes and interfaces that are extended from. It makes it possible to write code such as:
IComparer
Enumerators
An enumerator is an iterator.Enumerators are typically obtained by calling the method of an object implementing the interface. Container classes typically implement this interface. However, the foreach statement in C# can operate on any object providing such a method, even if it doesn't implement. This interface was expanded into generic version in.NET 2.0.
The following shows a simple use of iterators in C# 2.0:
// explicit version
IEnumerator
while )
Console.WriteLine;
// implicit version
foreach
Console.WriteLine;
Generator functionality
The.NET 2.0 Framework allowed C# to introduce an iterator that provides generator functionality, using a construct similar to in Python. With a, the function automatically keeps its state during the iteration.// Method that takes an iterable input
// and returns all even numbers.
public static IEnumerable
//using the method to output only even numbers from the array
static void Main
LINQ
LINQ, short for Language Integrated Queries, is a.NET Framework feature which simplifies the handling of data. Mainly it adds support that allows you to query arrays, collections, and databases. It also introduces binders, which makes it easier to access to databases and their data.Query syntax
The LINQ query syntax was introduced in C# 3.0 and lets you write SQL-like queries in C#.var list = new List
var result = from i in list
where i > 1
select i;
The statements are compiled into method calls, whereby almost only the names of the methods are specified. Which methods are ultimately used is determined by normal overload resolution. Thus, the end result of the translation is affected by what symbols are in scope.
What differs from SQL is that the from-statement comes first and not last as in SQL. This is because it seems more natural writing like this in C# and supports "Intellisense".
Anonymous methods
Anonymous methods, or in their present form more commonly referred to as "lambda expressions", is a feature which allows you to write inline closure-like functions in your code.There are various ways to create anonymous methods. Prior to C# 3.0 there was limited support by using delegates.
See also
- Anonymous function
- Closure
Anonymous delegates
Func
Lambda expressions
Lambda expressions provide a simple syntax for inline functions that are similar to closures. Functions with parameters infer the type of the parameters if other is not explicitly specified.// =>
// With parameters
n => n 2
=> a + b
=>
// With explicitly typed parameters
=> a + b
// No parameters
=> return 0
// Assigning lambda to delegate
Func
Multi-statement lambdas have bodies enclosed by braces and inside of them code can be written like in standard methods.
=>
Lambda expressions can be passed as arguments directly in method calls similar to anonymous delegates but with a more aesthetic syntax.
var list = stringList.Where;
Lambda expressions are essentially compiler-generated methods that are passed via delegates. These methods are reserved for the compiler only and can not be used in any other context.
Extension methods
Extension methods are a form of syntactic sugar providing the illusion of adding new methods to the existing class outside its definition. In practice, an extension method is a static method that is callable as if it were an instance method; the receiver of the call is bound to the first parameter of the method, decorated with keyword :public static class StringExtensions
string s = "foo";
s.Left; // same as StringExtensions.Left;
See also
- Decorator pattern
Local functions
In code example below, the Sum method is a local function inside Main method. So it can be used only inside its parent method Main:
static void Main
Miscellaneous
Closure blocks
C# implements closure blocks by means of the . The statement accepts an expression which results in an object implementing, and the compiler generates code that guarantees the object's disposal when the scope of the -statement is exited. The statement is syntactic sugar. It makes the code more readable than the equivalent block.public void Foo
Thread synchronization
C# provides the , which is yet another example of beneficial syntactic sugar. It works by marking a block of code as a critical section by mutual exclusion of access to a provided object. Like the statement, it works by the compiler generating a block in its place.private static StreamWriter _writer;
public void ConcurrentMethod
Attributes
Attributes are entities of data that are stored as metadata in the compiled assembly. An attribute can be added to types and members like properties and methods. Attributes better maintenance of preprocessor directives.public class $AnonymousType$120
The.NET Framework comes with predefined attributes that can be used. Some of them serve an important role at runtime while some are just for syntactic decoration in code like. It does only mark that it is a compiler-generated element. Programmer-defined attributes can also be created.
An attribute is essentially a class which inherits from the class. By convention, attribute classes end with "Attribute" in their name. This will not be required when using it.
public class EdibleAttribute : Attribute
Showing the attribute in use using the optional constructor parameters.
public class Peach : Fruit
Preprocessor
C# features "preprocessor directives" based on the C preprocessor that allow programmers to define symbols, but not macros. Conditionals such as,, and are also provided.Directives such as give hints to editors for code folding. The block must be terminated with a directive.
public class Foo
Code comments
C# utilizes a double slash to indicate the rest of the line is a comment.public class Foo
Multi-line comments can be indicated by a starting slash/asterisk and ending asterisk/forward slash.
public class Foo
Comments do not nest. These are two single comments:
// Can put /* */ */ */ /* /*
/* Can put /* /* /* but it ends with */
Single-line comments beginning with three slashes are used for XML documentation. This, however, is a convention used by Visual Studio and is not part of the language definition:
///
/// This class is very classy.
///
XML documentation system
C#'s documentation system is similar to Java's Javadoc, but based on XML. Two methods of documentation are currently supported by the C# compiler.Single-line documentation comments, such as those commonly found in Visual Studio generated code, are indicated on a line beginning with.
public class Foo
Multi-line documentation comments, while defined in the version 1.0 language specification, were not supported until the.NET 1.1 release. These comments are designated by a starting forward slash/asterisk/asterisk and ending asterisk/forward slash.
public class Foo
There are some stringent criteria regarding white space and XML documentation when using the forward slash/asterisk/asterisk technique.
This code block:
/**
*
* A summary of the method.
produces a different XML comment than this code block:
/**
*
A summary of the method.
Syntax for documentation comments and their XML markup is defined in a non-normative annex of the ECMA C# standard. The same standard also defines rules for processing of such comments, and their transformation to a plain XML document with precise rules for mapping of Common Language Infrastructure identifiers to their related documentation elements. This allows any C# integrated development environment or other development tool to find documentation for any symbol in the code in a certain well-defined way.
Async-await syntax
As of.NET Framework 4 there is a task library that makes it easier to write parallel and multi-threaded applications through tasks.C# 5.0 has native language support for asynchrony.
Consider this code that takes advantage of the task library directly:
public static class SomeAsyncCode
var t = SomeAsyncCode.GetContentAsync.ContinueWith;
t.Start;
Here is the same logic written in the async-await syntax:
public static class SomeAsyncCode
var xmlDocument = await SomeAsyncCode.GetContentAsync;
// The Task will be started on call with await.
Dialects
Spec#
Spec# is a dialect of C# that is developed in parallel with the standard implementation from Microsoft. It extends C# with specification language features and is a possible future feature to the C# language. It also adds syntax for the code contracts API that was introduced in.NET Framework 4.0. Spec# is being developed by Microsoft Research.This sample shows two of the basic structures that are used when adding contracts to your code.
static void Main
requires args.Length > 0
- is used to make a reference type non-nullable, e.g. you cannot set the value to. This in contrast of nullable types which allow value types to be set as.
- indicates a condition that must be followed in the code. In this case the length of args is not allowed to be zero or less.
Non-nullable types
string! input
In use:
public Test
Preconditions
Preconditions are checked before a method is executed.public Test
requires i > 0;
Postconditions
Postconditions are conditions that are ensured to be correct when a method has been executed.public void Increment
ensures i > 0;
Checked exceptions
Spec# adds checked exceptions like those in Java.public void DoSomething
throws SomeException; // SomeException : ICheckedException
Checked exceptions are problematic, because when a lower-level function adds a new exception type, the whole chain of methods using this method at some nested lower level must also change its contract. This violates the open/closed principle.