C Sharp syntax

Set of rules defining correctly structured programs for the C# programming language


title: "C Sharp syntax" type: doc version: 1 created: 2026-02-28 author: "Wikipedia contributors" status: active scope: public tags: ["c-sharp-(programming-language)", "programming-language-syntax"] description: "Set of rules defining correctly structured programs for the C# programming language" topic_path: "linguistics" source: "https://en.wikipedia.org/wiki/C_Sharp_syntax" license: "CC BY-SA 4.0" wikipedia_page_id: 0 wikipedia_revision_id: 0

::summary Set of rules defining correctly structured programs for the C# programming language ::

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 a code element. It can contain letters, digits and underscores (_), and is case sensitive (FOO is different from foo). The language imposes the following restrictions on identifier names:

  • They cannot start with a digit;
  • They cannot start with a symbol, except for the at sign (@), which can be used to prefix keywords to allow them as identifiers;
  • They cannot contain more than 511 characters.

Identifier names may be prefixed by @, which allows the use of reserved keywords as identifiers (for example, @class), but the @ is not considered part of the identifier's name for most purposes; @name and name refer to the same identifier unless name is a keyword.

Microsoft offered naming conventions for identifiers in C#, recommending the use of PascalCase for the names of types and most type members, and camelCase for variables and for private or internal fields. These naming conventions are not enforced by the language.

Keywords

Keywords

Keywords are words with syntactic meaning. The language has two types of keyword — contextual and reserved. Reserved keywords such as false or byte may only be used as keywords. Contextual keywords such as where or from are treated as keywords only in certain situations.{{citation |first=Herbert |last=Schildt |title=C# 3.0: The Complete Reference |date=December 30, 2008 |isbn=9780071588416 |url=https://books.google.com/books?id=nn6wbI45XDAC&pg=PA32}} If an identifier is needed that matches a reserved keyword, it is prefixed by an @ sign to distinguish it. For example, @out is interpreted as an identifier, whereas out is a keyword. This syntax facilitates reuse of .NET code written in other languages.

The following C# keywords are reserved words, of which there are 77.

  • abstract
  • as
  • base
  • bool
  • break
  • byte
  • case
  • catch
  • char
  • checked
  • class
  • const
  • continue
  • decimal
  • default
  • delegate
  • do
  • double
  • else
  • enum
  • event
  • explicit
  • extern
  • false
  • finally
  • fixed
  • float
  • for
  • foreach
  • goto
  • if
  • implicit
  • in
  • int
  • interface
  • internal
  • is
  • lock
  • long
  • namespace
  • new
  • null
  • object
  • operator
  • out
  • override
  • params
  • private
  • protected
  • public
  • readonly
  • ref
  • return
  • sbyte
  • sealed
  • short
  • sizeof
  • stackalloc
  • static
  • string
  • struct
  • switch
  • this
  • throw
  • true
  • try
  • typeof
  • uint
  • ulong
  • unchecked
  • unsafe
  • ushort
  • using
  • virtual
  • void
  • volatile
  • while

Contextual keywords

Contextual keywordsA contextual keyword is used to provide a specific meaning in the code, but it is not a reserved word in C#. Some contextual keywords, such as partial and where, have meanings in multiple contexts. The following 42 C# keywords are contextual.

  • add
  • allows
  • alias
  • and
  • ascending
  • args
  • async
  • await
  • by
  • descending
  • dynamic
  • equals
  • from
  • get
  • global
  • group
  • init
  • into
  • join
  • let
  • managed
  • nameof
  • nint
  • not
  • notnull
  • nuint
  • on
  • or
  • orderby
  • partial
  • record
  • remove
  • required
  • select
  • set
  • unmanaged
  • value
  • var
  • when
  • where
  • with
  • yield

Preprocessor directives

Although C# does not have a separate preprocessor, unlike C and C++ which use the C preprocessor, these 13 directives are processed as if there were one.

  • #nullable
  • #if
  • #elif
  • #else
  • #endif
  • #define
  • #undef
  • #region
  • #endregion
  • #error
  • #warning
  • #line
  • #pragma

Literals

::data[format=table title="Integers{{Cite web |last=Wagner |first=Bill |date= |title=Integral numeric types |url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types |access-date=2024-10-27 |website=learn.microsoft.com |language=en-us}}"]

decimalhexadecimalbinary
::

::data[format=table title="[[Floating-point]] values{{Cite web |last=Wagner |first=Bill |date= |title=Floating-point numeric types |url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types |access-date=2024-10-27 |website=learn.microsoft.com |language=en-us}}"]

floatdoubledecimal
::

::data[format=table title="Characters{{Cite web |last=Wagner |first=Bill |date= |title=char |url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/char |access-date=2024-10-27 |website=learn.microsoft.com |language=en-us}}"]

char
::

::data[format=table title="Strings{{Cite web |last=Wagner |first=Bill |date= |title=Strings and string literals |url=https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/ |access-date=2024-10-27 |website=learn.microsoft.com |language=en-us}}"]

string
{{br list
::

::data[format=table title="Character escapes in strings"]

Unicode characterExtended_ASCII characterNull characterTabBackspaceCarriage returnForm feedBackslashSingle quoteDouble quoteLine feed
followed by the hexadecimal unicode code point
followed by the hexadecimal extended ASCII code point
Null character
Tab
Backspace
Carriage return (moves cursor to the start of the current line)
Form feed (page break)
Backslash
Single quote
Double quote
Line feed (moves cursor to the next line)
::

Digit separators

Starting in C# 7.0, the underscore symbol can be used to separate digits in number values for readability purposes. The compiler ignores these underscores. ::code[lang=csharp] 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, separators may be put only between digit characters. It cannot be put at the beginning () or the end of the value ( or ), next to the decimal in floating point values (), next to the exponent character (), or next to the type specifier ().

Variables

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 ::code[lang=csharp] int myInt; // Declaring an uninitialized variable called 'myInt', of type 'int' ::

Assigning ::code[lang=csharp] int myInt; // Declaring an uninitialized variable myInt = 35; // Assigning the variable a value ::

Initialize ::code[lang=csharp] int myInt = 35; // Declaring and initializing the variable ::

Multiple variables of the same type can be declared and initialized in one statement. ::code[lang=csharp] 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

:This is a feature of C# 3.0.

C# 3.0 introduced type inference, allowing the type specifier of a variable declaration to be replaced by the keyword var, 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. ::code[lang=csharp] var myChars = new char[] {'A', 'Ö'}; // equivalent to: char[] myChars = new char[] {'A', 'Ö'};

var myNums = new List

Constants

Constants are immutable values.

const

When declaring a local variable or a field with the const keyword as a prefix the value must be given when it is declared. Thereafter the value cannot change. They can either be declared in the context as a field or a local variable. Constants are implicitly static. ::code[lang=csharp] const double PI = 3.14; ::

This shows both uses of the keyword. ::code[lang=csharp] public class Foo { private const double X = 3;

public Foo()
{
    const int y = 2;
}

} ::

readonly

The readonly keyword does a similar thing to fields. Like fields marked as const their value cannot change once initialized. The difference is that one can choose to initialize them in a constructor, or to a value that is not known until run-time. This works only on fields. readonly fields can either be members of an instance or static class members.

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, braces can be used to create new scopes: ::code[lang=csharp] void DoSomething() { int a;

{
    int b;
    a = 1;
}

a = 2;
b = 3; // Will fail because the variable is declared in an inner scope.

} ::

Program structure

A C# application consists of classes and their members. Classes and other types exist in namespaces and can be nested inside other classes.

Main method

Every program must have an entry point. The entry point of a C# application is the Main method. There can only be one declaration of this method, and it is a static method in a class. It usually returns void and is passed command-line arguments as an array of strings. ::code[lang=c#] static void Main(string[] args) // string[] args can be omitted if the program doesn't have any command-line arguments. { } ::

The main method may return an integer value if specified. ::code[lang=c#] static int Main(string[] args) { return 0; } ::

Async Main

This is a feature of C# 7.1.

Asynchronous Tasks can be awaited in the Main method by declaring the method's return type as Task. ::code[lang=c#] static async Task Main(string[] args) { await DoWorkAsync(42); } ::

All combinations of Task, or Task, and with, or without, the string[] args parameter are supported.

Top-level statements

This is a feature of C# 9.0.

Similar to in scripting languages, top-level statements remove the ceremony of having to declare the Program class with a Main method.

Instead, statements can be written directly in one file, which is the program entry point. Code in other files must be defined in classes.

This was introduced to make C# less verbose, and thus more accessible. using System;

Console.WriteLine("Hello World!"); Types are declared after the statements, and are available from the statements above them.

Namespaces

Namespaces are a part of a type name and are used to group and/or distinguish named entities from other ones. ::code[lang=csharp] System.IO.DirectoryInfo // DirectoryInfo is in the System.IO-namespace ::

A namespace is defined with the namespace keyword: ::code[lang=csharp] namespace FooNamespace { // Members } ::

A namespace can be nested inside a namespace in three ways: ::code[lang=c#] namespace FooNamespace { // Members namespace BarNamespace { // Members
} } ::

and: ::code[lang=c#] namespace FooNamspace { // Members }

namespace FooNamspace.BarNamespace { // Members } ::

In C# 10 and later, namespaces can be defined using file-scoped declarations by doing the following: ::code[lang=c#] namespace FooNamespace; // the brackets are omitted here in favor of a semicolon. ::

using directive

The using directive loads a specific namespace from a referenced assembly. It is usually placed in the top (or header) of a code file but it can be placed elsewhere, e.g. inside a class. ::code[lang=csharp] using System; using System.Collections; ::

The directive can also be used to define another name for an existing namespace or type. This is useful when names are long. ::code[lang=csharp] using Net = System.Net; using DirInfo = System.IO.DirectoryInfo; ::

{{C sharp|using static}} directive

The directive loads the static members of a specified type into the current scope, making them accessible directly by the name of the member. ::code[lang=csharp] using static System.Console;

WriteLine("Hello, World!"); ::

{{C sharp|global using}} directive

Since C# 10, it is legal to write directives to indicate a using directive once and apply it to all source files. ::code[lang=csharp] global using System; global using Microsoft.Extensions.FileSystemGlobbing; ::

Operators

::data[format=table]

Operator categoryOperators
Arithmetic, , , ,
Logical (boolean and bitwise), , , , , , , ,
String concatenation
Increment, decrement,
Shift
Relational (conditional), , ,
Assignment, , , , , , , , ,
Member access, ,
Indexing
Cast
Conditional (ternary)
Delegate concatenation and removal,
Object creation
Type information, , ,
Overflow exception control,
Indirection and Address, , ,
Coalesce
Lambda expression
::

Operator overloading

Some operators can be overloaded by writing an overload method. ::code[lang=csharp] public static Foo operator+(Foo foo, Bar bar) { return new Foo(foo.Value + bar.Value); } ::

These are the overloadable operators: ::data[format=table]

Operators
, , , , , , ,
, , , , , , , ,
}}, =
::
  • Assignment operators ( etc.) are combinations of a binary operator and the assignment operator () and is evaluated using the ordinary operators, which can be overloaded.
  • Cast operators () cannot be overloaded, but it is possible to define conversion operators.
  • Array indexing () operator is not overloadable, but it is possible to define new indexers.

Conversion operators

The cast operator is not overloadable, but a conversion operator method can live in the target class. Conversion methods can define two varieties of operators, implicit and explicit conversion operators. The implicit operator will cast without specifying with the cast operator () while the explicit operator requires it to be used.

Implicit conversion operator

::code[lang=csharp] class Foo { public int Value;

public static implicit operator Foo(int value)
{
    return new Foo(value);
}

} // Implicit conversion Foo foo = 2; ::

Explicit conversion operator

::code[lang=csharp] class Foo { public int Value;

public static explicit operator Foo(int value)
{
    return new Foo(value);
}

} // Explicit conversion Foo foo = (Foo)2; ::

as operator

The as 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. ::code[lang=csharp] Stream stream = File.Open(@"C:\Temp\data.dat"); FileStream fstream = stream as FileStream; // Will return an object.

String str = stream as String; // Will return null. ::

Null coalesce operator

:This is a feature of C# 2.0. The following: ::code[lang=csharp] return ifNotNullValue ?? otherwiseValue; ::

is shorthand for: ::code[lang=csharp] return ifNotNullValue != null ? ifNotNullValue : otherwiseValue; ::

Meaning that if the content of variable is not null, that content is returned, otherwise the content of variable is returned.

C# 8.0 introduces null-coalescing assignment, such that ::code[lang=csharp] variable ??= otherwiseValue; ::

is equivalent to ::code[lang=csharp] if (variable is null) variable = otherwiseValue; ::

Control structures

C# inherits most of the control structures of C/C++ and adds others such as the foreach statement.

Conditional structures

These structures control the flow of the program through given conditions.

if statement

The if 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.

A simple one-line statement: ::code[lang=csharp] if (i == 3) ... ; ::

Multi-line with else-block (without any braces): ::code[lang=csharp] if (i == 2) ... else ... ::

Recommended coding conventions for an if-statement. ::code[lang=csharp] if (i == 3) { ... } else if (i == 2) { ... } else { ... } ::

switch statement

The switch construct serves as a filter for different values. Each value leads to a "case". Falling through case sections is not allowed and therefore the keyword break is typically used to end a case. An unconditional return in a case section can also be used to end a case. goto statements can be used to fall through from one case to the next. The default case handles all cases not explicitly handled by the construct. ::code[lang=csharp] switch (ch) { case 'A': statement; ... break; case 'B': statement; break; case 'C': // A switch section can have multiple case labels. case 'D': ... break; default: ... break; } ::

Iteration structures

Iteration statements are statements that repeatedly execute when a given condition evaluates as true.

while loop

::code[lang=csharp] while (i == true) { ... } ::

do ... while loop

::code[lang=csharp] do {

} while (i == true); ::

for loop

The for loop consists of three parts: declaration, condition and counter expression. All are optional. ::code[lang=csharp] for (int i = 0; i < 10; i++) { ... } ::

Is equivalent to this code represented with a while statement, except here the variable is not local to the loop. ::code[lang=csharp] int i = 0; while (i < 10) { //... i++; } ::

foreach loop

The foreach statement is derived from the for 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 is returned in the context of the code block. When the block has been executed the next item is returned until there are no items remaining. ::code[lang=csharp] foreach (int i in intList) { ... } ::

Jump statements

Jump statements are inherited from C/C++ and ultimately assembly languages through it. They represent the jump-instructions of an assembly language that controls the flow of a program.

Labels and goto statement

Labels are given points in code that can be jumped to by using the goto statement. ::code[lang=csharp] start: ....... goto start; ::

Note that the label need not be positioned after the goto statement; it may be before it in the source file.

The goto statement can be used in switch statements to jump from one case to another or to fall through from one case to the next. ::code[lang=csharp] switch (n) { case 1: Console.WriteLine("Case 1"); break; case 2: Console.WriteLine("Case 2"); goto case 1; case 3: Console.WriteLine("Case 3"); case 4: // Compilation will fail here as cases cannot fall through in C#. Console.WriteLine("Case 4"); goto default; // This is the correct way to fall through to the next case. case 5: // Multiple labels for the same code are OK case 6: default: Console.WriteLine("Default"); break; // Even default must not reach the end point } ::

break statement

The break statement breaks out of the closest loop or switch statement. Execution continues in the statement after the terminated statement, if any. ::code[lang=csharp] int e = 10; for (int i = 0; i < e; i++) { while (true) { break; } // Will break to this point. } ::

continue statement

The continue statement discontinues the current iteration of the current control statement and begins the next iteration. ::code[lang=csharp] int ch; while ((ch = Console.Read()) != -1) { if (ch == ' ') { continue; // Skips the rest of the while-loop }

// Rest of the while-loop
...

} ::

The while 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: ::code[lang=csharp] throw new NotImplementedException(); ::

{{C sharp|try ... catch ... finally}} statements

Exceptions are managed within blocks. ::code[lang=csharp] try { // Statements which may throw exceptions ... } catch (Exception ex) { // Exception caught and handled here ... } finally { // Statements always executed after the try/catch blocks ... } ::

The statements within the try block are executed, and if any of them throws an exception, execution of the block is discontinued and the exception is handled by the catch block. There may be multiple catch blocks, in which case the first block with an exception variable whose type matches the type of the thrown exception is executed.

If no catch block matches the type of the thrown exception, the execution of the outer block (or method) containing the try ... catch 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 catch 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 catch 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 finally block are always executed after the try and catch blocks, whether or not an exception was thrown.

Either a catch block, a finally block, or both, must follow the try 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 declared. The two kinds of types are value types and reference types.

Value types

Instances of value types reside on the stack, i.e. they are bound to their variables. If one declares a variable for a value type the memory gets allocated directly. If the variable falls out of scope it is destroyed.

Structures

Structures are more commonly known as structs. Structs are user-defined value types that are declared using the struct keyword. They are similar to classes but are more suitable for lightweight types. Some important syntactical differences between a class and a struct are presented later in this article. ::code[lang=csharp] struct Foo { ... } ::

The primitive data types are all structs.

Pre-defined types

::data[format=table]

Primitive typesType nameBCL equivalentValueRangeSizeDefault value
integer−128 through +1278-bit (1-byte)
integer−32,768 through +32,76716-bit (2-byte)
integer−2,147,483,648 through +2,147,483,64732-bit (4-byte)
integer−9,223,372,036,854,775,808 through
+9,223,372,036,854,775,80764-bit (8-byte)
unsigned integer0 through 2558-bit (1-byte)
unsigned integer0 through 65,53516-bit (2-byte)
unsigned integer0 through 4,294,967,29532-bit (4-byte)
unsigned integer0 through 18,446,744,073,709,551,61564-bit (8-byte)
signed decimal number−79,228,162,514,264,337,593,543,950,335 through
+79,228,162,514,264,337,593,543,950,335128-bit (16-byte)
floating point number±1.401298E−45 through ±3.402823E+3832-bit (4-byte)
floating point number±4.94065645841246E−324 through
±1.79769313486232E+30864-bit (8-byte)
Booleanor8-bit (1-byte)
single Unicode characterthrough16-bit (2-byte)
::

Note: () is not a struct and is not a primitive type.

Enumerations

Enumerated types (declared with enum) are named values representing integer values. ::code[lang=csharp] enum Season { Winter = 0, Spring = 1, Summer = 2, Autumn = 3, Fall = Autumn // Autumn is called Fall in American English. } ::

Enum variables are initialized by default to zero. They can be assigned or initialized to the named values defined by the enumeration type. ::code[lang=csharp] Season season; season = Season.Spring; ::

Enum 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 enum variables to and from integer types. However, the cast does not throw an exception if the value is not specified by the type definition. ::code[lang=csharp] season = (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 = (int)season; // Casting enum-value to integer value.

season++; // Season.Spring (1) becomes Season.Summer (2). season--; // Season.Summer (2) becomes Season.Spring (1). ::

Values can be combined using the bitwise-OR operator . ::code[lang=csharp] Color myColors = Color.Green | Color.Yellow | Color.Blue; ::

Reference types

Variables created for reference types are typed managed references. When the constructor is called, an object is created on the heap and a reference is assigned to the variable. When a variable of an object goes out of scope the reference is broken and when no references are left the object gets marked as garbage. The garbage collector then collects and destroys it.

A reference variable is null when it does not reference any object.

Arrays

An array type is a reference type that refers to a space containing one or more elements of a certain type. All array types derive from a common base class, . Each element is referenced by its index as in C++ and Java.

An array in C# is what is called a dynamic array in C++. ::code[lang=csharp] int[] numbers = new int[2]; numbers[0] = 2; numbers[1] = 5; int x = numbers[0]; ::

Initializers

Array initializers provide convenient syntax for initialization of arrays. ::code[lang=csharp] // Long syntax int[] numbers = new int[5]{ 20, 1, 42, 15, 34 }; // Short syntax int[] numbers2 = { 20, 1, 42, 15, 34 }; // Inferred syntax var numbers3 = new[] { 20, 1, 42, 15, 34 }; ::

Multi-dimensional arrays

Arrays can have more than one dimension, for example 2 dimensions to represent a grid. ::code[lang=csharp] int[,] numbers = new int[3, 3]; numbers[1,2] = 2;

int[,] numbers2 = new int[3, 3] { {2, 3, 2}, {1, 2, 6}, {2, 4, 5} }; ::

See also

Classes

Classes are self-describing user-defined reference types. Essentially all types in the .NET Framework are classes, including structs and enums, that are compiler generated classes. Class members are private by default, but can be declared as public to be visible outside of the class or protected to be visible by any descendants of the class.

Strings

The class, or , represents an immutable sequence of unicode characters ().

Actions performed on a string always return a new string. ::code[lang=csharp] string text = "Hello World!"; string substr = text.Substring(0, 5); string[] parts = text.Split(new char[]{ ' ' }); ::

The class can be used when a mutable "string" is wanted. ::code[lang=csharp] StringBuilder sb = new StringBuilder(); sb.Append('H'); sb.Append("el"); sb.AppendLine("lo!"); ::

Interface

Interfaces are data structures that contain member definitions without implementations. A variable of an interface type is a reference to an instance of a class which implements this interface. See #Interfaces.

Delegates

Main article: Delegate (CLI)

C# provides type-safe object-oriented function pointers in the form of delegates. ::code[lang=csharp] class Program { // Delegate type: delegate int Operation(int a, int b);

static int Add(int i1, int i2)
{
    return i1 + i2;
}

static int Sub(int i1, int i2)
{
    return i1 - i2;
}

static void Main()
{
    // Instantiate the delegate and assign the method to it.
    Operation op = Add;

    // Call the method that the delegate points to.
    int result1 = op(2, 3);  // 5

    op = Sub;
    int result2 = op(10, 2); // 8
}

} ::

Initializing the delegate with an anonymous method. ::code[lang=csharp] addition = delegate(int a, int b) { return a + b; }; ::

Initializing the delegate with lambda expression. ::code[lang=csharp] addition = (a, b) => a + b; ::

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 classic Visual Basic. ::code[lang=csharp] using System.Windows.Controls;

delegate void MouseEventHandler(object sender, MouseEventArgs e);

public class Button : Control { private event MouseEventHandler _onClick;

/* Imaginary trigger function */
void Click()
{
    _onClick(this, new MouseEventArgs(data));
}

} ::

An event requires an accompanied event handler that is made from a special delegate that in a platform specific library such as Windows Presentation Foundation and Windows Forms usually takes two parameters: sender and 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. ::code[lang=csharp] public class MainWindow : System.Windows.Controls.Window { private Button _button1;

public MainWindow()
{
    _button1 = new Button();
    _button1.Text = "Click me!";

    /* Subscribe to the event */
    _button1.ClickEvent += Button1_OnClick;

    /* Alternate syntax that is considered old:
    _button1.MouseClick += new MouseEventHandler(Button1_OnClick); */
}

protected void Button1_OnClick(object sender, MouseEventArgs e)
{
    MessageBox.Show("Clicked!");
}

} ::

Custom event implementation is also possible: ::code[lang=csharp] private EventHandler _clickHandles = (s, e) => { };

public event EventHandler Click
{
	add
	{
		// Some code to run when handler is added...
		...

		_clickHandles += value;
	}
	remove
	{
		// Some code to run when handler is removed...
		...

		_clickHandles -= value;
	}
}

::

See also

Nullable types

:This is a feature of C# 2.0.

Nullable types were introduced in C# 2.0 firstly to enable value types to be null (useful when working with a database). ::code[lang=csharp] int? n = 2; n = null;

Console.WriteLine(n.HasValue); ::

This is the same as using the struct. ::code[lang=csharp] Nullable

Console.WriteLine(n.HasValue); ::

Pointers

C# has and allows pointers to selected types (some primitives, enums, strings, pointers, and even arrays and structs if they contain only types that can be pointed{{citation |title=Pointer types (C# Programming Guide) |url=http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx}}) in unsafe context: methods and codeblock marked unsafe. These are syntactically the same as pointers in C and C++. However, runtime-checking is disabled inside unsafe blocks. ::code[lang=csharp] static void Main(string[] args) { unsafe { int a = 2; int* b = &a;

    Console.WriteLine("Address of a: {0}. Value: {1}", (int)&a, a);
    Console.WriteLine("Address of b: {0}. Value: {1}. Value of *b: {2}", (int)&b, (int)b, *b);

    // Will output something like:
    // Address of a: 71953600. Value: 2
    // Address of b: 71953596. Value: 71953600. Value of *b: 2
}

} ::

Structs are required only to be pure structs with no members of a managed reference type, e.g. a string or any other class. ::code[lang=csharp] public struct MyStruct { public char Character; public int Integer; }

public struct MyContainerStruct { public byte Byte; public MyStruct MyStruct; } ::

In use: ::code[lang=csharp] MyContainerStruct x; MyContainerStruct* ptr = &x;

byte value = ptr->Byte; ::

Dynamic

:This is a feature of C# 4.0 and .NET Framework 4.0. Type dynamic enables dynamic runtime lookup to C# in a static manner. Dynamic denotes a variable with an object with a type that is resolved at runtime, as opposed to compile-time.

This feature takes advantage of the Dynamic Language Runtime (DLR) and is designed with the goal of interoperation with dynamically typed languages like IronPython and IronRuby (Implementations of Python and Ruby for .NET).

Dynamic-support also eases interoperation with COM objects. ::code[lang=csharp] dynamic x = new Foo(); x.DoSomething(); // Will compile and resolved at runtime. An exception will be thrown if invalid. ::

Anonymous types

:This is a feature of C# 3.0. Anonymous types are nameless classes that are generated by the compiler. They are only consumable and yet useful in a scenario such as a LINQ query that returns an object on select to return some specific values. Then, 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. ::code[lang=csharp] var carl = new { Name = "Carl", Age = 35 }; // Name of the type is only known by the compiler. var mary = new { Name = "Mary", Age = 22 }; // 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 (previously boxed) into a value of a value type. Unboxing in C# requires an explicit type cast.

Example: ::code[lang=csharp] int foo = 42; // Value type. object bar = foo; // foo is boxed to bar. int foo2 = (int)bar; // Unboxed back to value type. ::

Object-oriented programming

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 syntactical distinction is made between those in code.

Object class

All types, even value types in their boxed form, implicitly inherit from the class, the base class. This class contains the most common methods shared by all objects. Some of these are virtual and can be overridden.

Classes inherit either directly or indirectly through another base class.

Members Some members of the Object class:

    • Supports comparisons between objects.
    • Performs cleanup operations before an object is automatically reclaimed. (Default destructor)
    • 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 returns the type name.

Classes

Classes are fundamentals of an object-oriented language such as C#. They serve as a template for objects. They contain members that store and manipulate data in a real-life like way.

Differences between classes and structs

Although classes and structures are similar in both the way they are declared and how they are used, some significant differences apply. Classes are reference types and structs are value types. A structure is allocated on the stack when it is declared and the variable is bound to its address. It directly contains the value. Classes are different because the memory is allocated on the heap. Variables are references, managed pointers on the stack which point to the objects.

Structures differ from classes in other ways. For example, while both offer an implicit default constructor that takes no arguments, it cannot be redefined for structs. Explicitly defining a differently-parametrized constructor overrides the implicit default constructor in classes, but not in structs. All fields of a struct must be initialized in those constructors. Structs do not have finalizers and cannot inherit from another class like classes do. Implicitly, they are sealed and inherit from (which inherits from ). Structs are more suitable for smaller amounts of data. ::data[format=table title="Differences"]

Default constructorFinalizerMember initializationInheritanceClassesStructs
not required (auto generated)yesnot requiredyes (if base class is not sealed)
required (auto generated)norequirednot supported
::

Declaration

Class declaration: ::code[lang=csharp] class Foo { // Member declarations } ::

Partial class

:This is a feature of C# 2.0.

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 partial. ::code[lang=csharp] // File1.cs partial class Foo { ... }

// File2.cs partial class Foo { ... } ::

The usual reason for using partial classes is to split some class into programmer-maintained and tool-maintained parts, i.e. some code is automatically generated by a user-interface designing tool or something alike.

Initialization

Before one can use the members of the class, initialize the variable with a reference to an object. To create it, call the appropriate constructor using the new keyword. It has the same name as the class. ::code[lang=csharp] Foo foo = new Foo(); StreamReader sr = new StreamReader("MyFile.txt"); ::

For structs it is optional to explicitly call a constructor because the default one is called automatically. It must be declared and it gets initialized with standard values.

To reduce boilerplate, if the type is given in a declaration (i.e. not using var), the constructor can be invoked with just new(). ::code[lang=csharp] Foo foo = new(); StreamReader sr = new("MyFile.txt"); ::

Object initializers

:This is a feature of C# 3.0. Provides a more convenient way of initializing public fields and properties of an object. Constructor calls are optional given a default constructor. ::code[lang=csharp] Person person = new Person { Name = "John Doe", Age = 39 };

// Equal to Person person = new Person(); person.Name = "John Doe"; person.Age = 39; ::

Collection initializers

:This is a feature of C# 3.0. Collection initializers give an array-like syntax for initializing collections. The compiler generates calls to the Add-method. This works for classes that implement the interface . ::code[lang=csharp] List

// Equal to List

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. ::code[lang=csharp] 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. ::code[lang=csharp] int r = String.Compare(foo, fooUpper); ::

Accessing a member through a pointer In unsafe code, members of a value (struct type) referenced by a pointer are accessed with the operator as in C and C++. ::code[lang=csharp] 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 notable is a sub-group containing the access modifiers.

Class modifiers
  • abstract - Specifies that a class serves only as a base class. It implemented in an inheriting class. Required for classes to have abstract methods.
  • sealed - Specifies that a class cannot be inherited.
Class member modifiers
  • abstract - Declares a method to be available in all derived non-abstract classes.
  • const - Specifies that a variable is a constant value that has to be initialized when it gets declared.
  • event - Declares an event.
  • extern - Specifies that a method signature without a body uses a DLL-import.
  • override - Specifies that a method or property declaration is an override of a virtual member or an implementation of a member of an abstract class.
  • readonly - Declares a field that can only be assigned values as part of the declaration or in a constructor in the same class.
  • unsafe - Specifies an unsafe context, which allows the use of pointers.
  • virtual - Specifies that a method or property declaration can be overridden by a derived class.
  • volatile - Specifies a field that can be modified by an external process and prevents an optimizing compiler from making guesses about the persistence of the current value of the field.
static modifier

The static modifier states that a member belongs to the class and not to a specific object. Classes marked static are only allowed to contain static members. Static members are sometimes referred to as class members since they apply to the class as a whole and not to its instances. ::code[lang=csharp] public class Foo { public static void Something() { ... } } // Calling the class method. Foo.Something(); ::

Access modifiers

Access modifiers, or inheritance modifiers, set the accessibility of classes, methods, and other members. Items marked can be reached from anywhere. members can only be accessed from the class they are declared in and hidden when inherited. Members with the modifier are , but accessible when inherited. classes and members are only accessible from inside of the declaring assembly.

Classes and structs are implicitly and members are implicitly if they do not have an access modifier. ::code[lang=csharp] public class Foo { public int Do() { return 0; }

public class Bar
{

}

} ::

::data[format=table title="Access modifier usage"]

Unnested typesMembers (incl. nested types)Accessible topublicprotected internalprotectedinternalprivate protectedprivate
yesyesall
noyessame class, derived classes, and everything in the same assembly
noyessame class and derived classes
yes (default)yeseverything in the same assembly
noyessame class, and derived classes in the same assembly
noyes (default)same class
::

Constructors

A constructor is a special method that is called 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 any value. Implicitly, they return the newly created object when called via the new operator. They may take parameters like any other method. The parameter-less constructor is special because it can be specified as a necessary constraint for a generic type parameter. ::code[lang=csharp] class Foo { Foo() { ... } } ::

Constructors can be public, private, protected or internal.

Destructor

The destructor is called when the object is collected by the garbage collector to perform manual clean-up. The default destructor method called can be overridden.

The syntax is similar to that of constructors. The difference is that the name is preceded by a ~ and it cannot include parameters. Only one destructor can be declared. ::code[lang=csharp] class Foo { ...

~Foo()
{
    ...
}

} ::

Finalizers are always private.

Methods

As in C and C++ functions group reusable code. The main difference is that functions, as in Java, have to reside inside of a class. A function is therefore called a method. A method has a return value, a name and usually parameters initialized when it is called with arguments. It can belong either to an instance of a class or be static. ::code[lang=csharp] class Foo { int Bar(int a, int b) { return a % b; } } ::

A method is called using notation on a specific variable, or as in the case of static methods, the name of a type. ::code[lang=csharp] Foo foo = new Foo(); int r = foo.Bar(7, 2);

Console.WriteLine(r); ::

ref and out parameters

Arguments pass by reference when calling a method with parameters preceded by keywords ref or out. These managed pointers come in handy when passing variables to be modified inside the method. The main difference between the two is that an out parameter must have been assigned within the method by the time the method returns. ref may or may not assign a new value, but the parameter variable has to be initialized before calling the function. ::code[lang=csharp] void PassRef(ref int x) { if (x == 2) { x = 10; } } int Z = 7; PassRef(ref Z);

void PassOut(out int x) { x = 2; } int Q; PassOut(out Q); ::

Optional parameters

:This is a feature of C# 4.0. C# 4.0 introduces optional parameters with default values as seen in C++. For example: ::code[lang=csharp] void Increment(ref int x, int dx = 1) { x += dx; }

int x = 0; Increment(ref x); // dx takes the default value of 1 Increment(ref x, 2); // dx takes the value 2 ::

In addition, to complement optional parameters, it is possible to explicitly specify parameter names in method calls, to selectively pass a subset of optional parameters for a method. The only restriction is that named parameters must be placed after 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: ::code[lang=csharp] 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: ::code[lang=csharp] 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); console.writeline("File saved successfully"); ::

With support for optional parameters, the code can be shortened as ::code[lang=csharp] doc.SaveAs(ref fileName); ::

extern

C# can call native code. A method signature is declared without a body and is marked as extern. The attribute references the desired DLL. ::code[lang=csharp] [DllImport("win32.dll")] static extern double Pow(double a, double b); ::

Fields

Fields, or instance variables, can be declared inside the class body to store data. ::code[lang=csharp] class Foo { double foo; } ::

Fields can be initialized directly when declared (unless declared in struct). ::code[lang=csharp] class Foo { double foo = 2.3; } ::

Modifiers for fields:

  • const - Makes the field a constant.
  • private - Makes the field private (default).
  • protected - Makes the field protected.
  • public - Makes the field public.
  • readonly - Allows the field to be initialized only once in a constructor.
  • static - Makes the field a static member, i.e. a class variable.

Properties

Properties bring field-like syntax and combine them with methods. A property can have two accessors: get and set. ::code[lang=csharp] public class Person { private string _name;

string Name
{
    get { return _name; }
    set { _name = value; }
}

}

// Using a property var person = new Person(); person.Name = "Robert"; ::

Modifiers for properties:

  • private - Makes the property private (default).
  • protected - Makes the property protected.
  • public - Makes the property public.
  • static - Makes the property a static member.

Modifiers for property accessors:

  • private - Makes the accessor private.
  • protected - Makes the accessor protected.
  • public - Makes the accessor public.

The default modifiers for the accessors are inherited from the property. Note that the accessor's modifiers can only be equal or more restrictive than the property's modifier.

Automatic properties

:This is a feature of C# 3.0. Auto-implemented properties use accessors without bodies so that the compiler generatea a backing field and the necessary code. ::code[lang=csharp] public double Width { get; private set; } ::

Indexers

Indexers add array-like indexing capabilities to objects. They are implemented in a way similar to properties. ::code[lang=csharp] internal class IntList { private int[] _items;

int this[int index]
{
    get { return _items[index]; }
    set { _items[index] = value; }
}

}

// Using an indexer IntList list = new IntList(); list[2] = 2; ::

Inheritance

Classes in C# may only inherit from one class. A class may derive from any class that is not marked as sealed. ::code[lang=csharp] class A { }

class B : A {

} ::

virtual

Methods marked virtual provide an implementation that can be overridden by inheritors by using the override keyword.

The implementation is chosen by the type of the object and not the type of the variable. ::code[lang=csharp] class Operation { public virtual int Do() { return 0; } }

class NewOperation : Operation { public override int Do() { return 1; } } ::

new

When overloading a non-virtual method with another signature, the keyword new may be used. The method used is chosen by the variable type instead of the object type. ::code[lang=csharp] class Operation { public int Do() { return 0; } }

class NewOperation : Operation { public new double Do() { return 4.0; } } ::

This demonstrates the case: ::code[lang=csharp] NewOperation op = new NewOperation();

// Will call "double Do()" in NewOperation double d = op.Do();

Operation op_ = op;

// Will call "int Do()" in Operation int i = op_.Do(); ::

abstract

Abstract classes are classes that serve as templates and cannot be initialized. Otherwise, it is just like an ordinary class.

Abstract members are members of abstract classes that have no implementation. They must be overridden by non-abstract classes that inherit the member. ::code[lang=csharp] abstract class Mammal { public abstract void Walk(); }

class Human : Mammal { public override void Walk() {

}

...

} ::

sealed

The sealed modifier can be combined with the others to make them uninheritable, or for methods to disallow overriding them in derived classes.

::code[lang=csharp] internal sealed class Foo { //... }

public class Bar { public virtual void Action() { //... } }

public class Baz : Bar { public sealed override void Action() { //... } }

::

Interfaces

Interfaces are data structures that contain member definitions, but not implementations. They are used to define a contract between members in different types that have different implementations. Definitions can be supplied for methods, properties, and indexers. Interface members are implicitly public. An interface can either be implicitly or explicitly implemented. ::code[lang=csharp] interface IBinaryOperation { double A { get; set; } double B { get; set; }

double GetResult();

} ::

Implementing an interface

An interface is implemented by a class or extended by another interface in the same way a class is derived from another class using the notation.

Implicit implementation

When implicitly implementing an interface the members of the interface have to be public. ::code[lang=csharp] public class Adder : IBinaryOperation { public double A { get; set; } public double B { get; set; }

public double GetResult()
{
    return A + B;
}

}

public class Multiplier : IBinaryOperation { public double A { get; set; } public double B { get; set; }

public double GetResult()
{
    return A * B;
}

} ::

In use: ::code[lang=csharp] 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

Explicitly implemented members are accessible only when the object is handled as the interface type. ::code[lang=csharp] public class Adder : IBinaryOperation { double IBinaryOperation.A { get; set; } double IBinaryOperation.B { get; set; }

double IBinaryOperation.GetResult()
{
    return ((IBinaryOperation)this).A + ((IBinaryOperation)this).B;
}

} ::

In use: ::code[lang=csharp] 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(); ::

Properties in the class that extends are auto-implemented by the compiler and a backing field is automatically added (see #Automatic properties).

Extending multiple interfaces

Interfaces and classes are allowed to extend multiple interfaces. ::code[lang=csharp] class MyClass : IInterfaceA, IInterfaceB { ... } ::

An interface that extends two interfaces. ::code[lang=csharp] 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 extend only other interfaces.
  • An abstract class may have non-public methods and properties (also abstract ones). An interface can have only 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

:This is a feature of C# 2.0 and .NET Framework 2.0.

Generics (or parameterized types, parametric polymorphism) use type parameters, which make it possible to design classes and methods that do not specify the type used until the class or method is instantiated. The main advantage is that one can use generic type parameters to create classes and methods that can be used without incurring the cost of runtime casts or boxing operations, as:

::code[lang=csharp] // Declare the generic class.

public class GenericList { void Add(T input) { } }

class TestGenericList { private class ExampleClass { } static void Main() { // Declare a list of type int. GenericList

    // Declare a list of type string.
    GenericList<string> list2 = new GenericList<string>();

    // Declare a list of type ExampleClass.
    GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
}

} ::

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 (CLI) Virtual Machine, which allows for optimizations and preservation of the type information.{{cite web |url=http://msdn.microsoft.com/en-us/library/ms379564.aspx |title=An Introduction to C# Generics |date=January 2005 |publisher=Microsoft |access-date=June 18, 2009

Using generics

Generic classes

Classes and structs can be generic. ::code[lang=csharp] public class List { ... public void Add(T item) { ... } }

var list = new List

Generic interfaces

::code[lang=csharp] interface IEnumerable { ... } ::

Generic delegates

::code[lang=csharp] delegate R Func<T1, T2, R>(T1 a1, T2 a2); ::

Generic methods

::code[lang=csharp] public static T[] CombineArrays(T[] a, T[] b) { T[] newArray = new T[a.Length + b.Length]; a.CopyTo(newArray, 0); b.CopyTo(newArray, a.Length); return newArray; }

string[] a = new string[] { "a", "b", "c" }; string[] b = new string[] { "1", "2", "3" }; string[] c = CombineArrays(a, b);

double[] da = new double[] { 1.2, 2.17, 3.141592 }; double[] db = new double[] { 4.44, 5.6, 6.02 }; double[] dc = CombineArrays(da, db);

// c is a string array containing { "a", "b", "c", "1", "2", "3"} // dc is a double array containing { 1.2, 2.17, 3.141592, 4.44, 5.6, 6.02} ::

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 (or calling) a generic, one can then substitute a concrete type for the type-parameter one gave in its declaration. Type parameters may be constrained by use of the where keyword and a constraint specification, any of the six comma separated constraints may be used:

::data[format=table]

ConstraintExplanation
type parameter must be a value type
type parameter must be a reference type
type parameter must have a constructor with no parameters (must appear last)
type parameter must inherit from
type parameter must be, or must implement this interface
naked type parameter constraint
::

Covariance and contravariance

:This is a feature of C# 4.0 and .NET Framework 4.0.

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 has been redefined as follows: ::code[lang=csharp] interface IEnumerable { IEnumerator GetEnumerator(); } ::

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: ::code[lang=csharp] void PrintAll(IEnumerable objects) { foreach (object o in objects) { System.Console.WriteLine(o); } }

IEnumerable strings = new List(); PrintAll(strings); // IEnumerable is implicitly converted to IEnumerable ::

For contravariance, the existing interface has been redefined as: ::code[lang=csharp] 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: ::code[lang=csharp] IComparer objectComparer = GetComparer(); IComparer stringComparer = objectComparer; ::

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: ::code[lang=csharp] // explicit version IEnumerator iter = list.GetEnumerator(); while (iter.MoveNext()) { Console.WriteLine(iter.Current); }

// implicit version foreach (MyType value in list) { Console.WriteLine(value); } ::

Generator functionality

:This is a feature of C# 2.0. The .NET 2.0 Framework allowed C# to introduce an iterator that provides generator functionality, using a construct similar to yield in Python.{{cite web |url=http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80).aspx |title=yield |work=C# Language Reference |publisher=Microsoft |access-date=April 26, 2009}} With a , the function automatically keeps its state during the iteration. ::code[lang=csharp] // Method that takes an iterable input (possibly an array) // and returns all even numbers. public static IEnumerable

// using the method to output only even numbers from the array static void Main() { int[] numbers = { 1, 2, 3, 4, 5, 6}; foreach (int i in GetEven(numbers)) { Console.WriteLine(i); // outputs 2, 4 and 6 } } ::

LINQ

:This is a feature of C# 3.0 and .NET Framework 3.0. Main article: LINQ

LINQ, short for Language Integrated Queries, is a .NET Framework feature which simplifies the handling of data. Mainly it supports querying of arrays, collections, and databases. It introduces binders, which makes it easier to access to databases and their data.

Query syntax

LINQ query syntax was introduced in C# 3.0 and supports SQL-like queries. ::code[lang=csharp] List

IEnumerable

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 result of the translation is affected by the symbols in scope.

What differs from SQL is that the from-statement comes first and not last as in SQL. This seems more natural writing in C# and supports "Intellisense" (Code completion in the editor).

Anonymous methods

Anonymous methods, (lambda expressions), is a feature that allows programmers to write inline closure-like functions.

C# supports various ways to create anonymous methods.

Anonymous delegates

:This is a feature of C# 2.0.

Anonymous delegates are function pointers that hold anonymous methods. The purpose is to make it simpler to use delegates by simplifying function assignment. Instead of declaring a separate method in code the programmer can use the syntax to write the code inline and the compiler generates an anonymous function for it. ::code[lang=csharp] Func<int, int> f = delegate(int x) { return x * 2; }; ::

Lambda expressions

:This is a feature of C# 3.0. 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. ::code[lang=csharp] // [arguments] => [method-body]

// With parameters n => n == 2 (a, b) => a + b (a, b) => { a++; return a + b; }

// With explicitly typed parameters (int a, int b) => a + b

// No parameters () => return 0

// Assigning lambda to delegate Func<int, int, int> f = (a, b) => a + b; ::

Multi-statement lambdas have bodies enclosed by braces and inside of them code can be written as in standard methods. ::code[lang=csharp] (a, b) => { a++; return a + b; } ::

Lambda expressions can be passed as arguments directly in method calls similar to anonymous delegates but with a cleaner syntax. ::code[lang=csharp] var list = stringList.Where(n => n.Length > 2); ::

Lambda expressions are compiler-generated methods passed via delegates. These methods are reserved for the compiler and cannot be used in any other context.

Extension methods

:This is a feature of C# 3.0. Extension methods are syntactic sugar providing the illusion of adding new methods to an 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 this: ::code[lang=csharp] public static class StringExtensions { public static string Left(this string s, int n) { return s.Substring(0, n); } }

string s = "foo"; s.Left(3); // same as StringExtensions.Left(s, 3); ::

Local functions

:This is a feature of C# 7.0.

Local functions can be defined in the body of another method, constructor or property's getter and setter. Such functions have access to all variables in the enclosing scope, including parent method local variables. They are in scope for the entire method, regardless of whether they are invoked before or after their declaration. Access modifiers (public, private, protected) cannot be used with local functions. They do not support function overloading, which means two local functions in the same method cannot have the same name even if the signatures don't overlap. After a compilation, a local function is transformed into a private static method, but when defined it cannot be marked static.

In the example below, the Sum method is a local function inside Main method. So it can be used only inside its parent method Main: ::code[lang=csharp] static void Main(string[] args) { int Sum(int x, int y) { return x + y; }

Console.WriteLine(Sum(10, 20));
Console.ReadKey();

} ::

Miscellaneous

Closure blocks

C# implements closure blocks by means of the using statement. The using statement accepts an expression which results in an object implementing , and the compiler generates code that guarantees the object's disposal when exiting the scope of the using-statement. The using statement is syntactic sugar. It makes the code more readable than the equivalent block. ::code[lang=csharp] public void Foo() { using (FileStream bar = File.Open("Foo.txt")) { // do some work throw new Exception(); // bar will still get properly disposed. } } ::

Thread synchronization

C# provides the lock statement, which is 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 using statement, the compiler generates a block in its place. ::code[lang=csharp] private static StreamWriter _writer;

public void ConcurrentMethod() { lock (_writer) { _writer.WriteLine("Line 1."); _writer.WriteLine("Followed by line 2."); } } ::

Attributes

Attributes are entities of data that are stored as metadata in the compiled assembly, similar to Java annotations. An attribute can be added to types and members like properties and methods. Attributes can be used for better maintenance of preprocessor directives. ::code[lang=csharp] [CompilerGenerated] public class $AnonymousType$120 { [CompilerGenerated] public string Name { get; set; } } ::

The .NET Framework comes with predefined attributes that can be used. Some of them serve an important role at runtime, while others are just for syntactic decoration in code like . It only marks that it is a compiler-generated element. Programmer-defined attributes can also be created.

An attribute is essentially a class that inherits from the class. By convention, attribute classes end with "Attribute" in their name. This is not required when using it. ::code[lang=csharp] public class EdibleAttribute : Attribute { public EdibleAttribute() : base() {

}

public EdibleAttribute(bool isNotPoisonous)
{
    this.IsPoisonous = !isNotPoisonous;
}

public bool IsPoisonous { get; set; }

} ::

Showing the attribute in use using the optional constructor parameters. ::code[lang=csharp] [Edible(true)] public class Peach : Fruit { // Members if any } ::

Preprocessor

Main article: C preprocessor

C# features "preprocessor directives"{{cite web |url=http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx |title=C# Preprocessor Directives |work=C# Language Reference |publisher=Microsoft |access-date=June 18, 2009

Directives such as give hints to editors for code folding. The block must be terminated with a directive. ::code[lang=csharp] public class Foo { #region Constructors public Foo() {} public Foo(int firstParam) {} #endregion

#region Methods
public void IntBar(int firstParam) {}
public void StrBar(string firstParam) {}
public void BoolBar(bool firstParam) {}
#endregion

} ::

Code comments

C# utilizes a double slash () to indicate the rest of the line is a comment. ::code[lang=csharp] public class Foo { // a comment public static void Bar(int firstParam) {} // Also a comment } ::

Multi-line comments can be indicated by a starting slash/asterisk () and ending asterisk/forward slash (). ::code[lang=csharp] public class Foo { /* A multi-line comment */ public static void Bar(int firstParam) {} } ::

Comments do not nest. These are two single comments: ::code[lang=csharp] // Can put /* */ / / / / ::

::code[lang=csharp] /* Can put /* /* /* but it ends with */ ::

Single-line comments beginning with three slashes are used for XML documentation. This, however, is a Visual Studio convention and is not part of the language definition: ::code[lang=csharp] ///

/// This class is very classy. /// ::

XML documentation comments

C#'s documentation comments{{cite web |url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/#xml-comment-formats |title=Documentation comments |website=Microsoft Learn |date=2023-06-15

Single-line documentation comments, such as those commonly found in Visual Studio generated code, are indicated on a line beginning with . ::code[lang=csharp] public class Foo { ///

A summary of the method. /// A description of the parameter. /// Remarks about the method. public static void Bar(int firstParam) {} } ::

Multi-line documentation comments, while defined in the version 1.0 language specification, were not supported until the .NET 1.1 release.{{cite web |url=http://blogs.msdn.com/ansonh/archive/2006/09/11/750056.aspx |title=C# XML documentation comments FAQ |first=Anson |last=Horton |date=September 11, 2006 |access-date=December 11, 2007 |url=http://msdn.microsoft.com/en-us/library/5fz4y783(VS.71).aspx |title=Delimiters for Documentation Tags |work=C# Programmer's Reference |publisher=Microsoft |access-date=June 18, 2009 |url-status=dead |archive-url=https://web.archive.org/web/20081220051955/http://msdn.microsoft.com/en-us/library/5fz4y783(VS.71).aspx |archive-date=December 20, 2008 ::code[lang=csharp] public class Foo { /**

A summary of the method. * A description of the parameter. * Remarks about the method. */ public static void Bar(int firstParam) {} } ::

Stringent criteria governs white space and XML documentation when using the forward slash/asterisk/asterisk () technique.

This code block: ::code[lang=csharp] /**

  • A summary of the method.*/ ::

produces a different XML comment than this code block: ::code[lang=csharp] /**

  • 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 (CLI) identifiers to their related documentation elements. This allows any C# integrated development environment (IDE) or other development tool to find documentation for any symbol in the code in a certain well-defined way.

Async-await syntax

:This is a feature of C# 5.0 and .NET Framework 4.0.

As of .NET Framework 4 a task library makes it easier to write parallel and multi-threaded applications through tasks.

C# 5.0 has native language support for asynchrony, e.g: public static class SomeAsyncCode { public static Task GetContentAsync() { HttpClient hc = new HttpClient(); return hc.GetStringAsync("https://www.contoso.com/").ContinueWith((task) = { string responseBodyAsText = task.Result; return XDocument.Parse(responseBodyAsText); }); } }

var t = SomeAsyncCode.GetContentAsync().ContinueWith((task) = { XDocument xmlDocument = task.Result; });

t.Start();

The same logic written in the async-await syntax: ::code[lang=csharp] public static class SomeAsyncCode { public static async Task GetContentAsync() { HttpClient hc = new HttpClient(); string responseBodyAsText = await hc.GetStringAsync("https://www.contoso.com/"); return XDocument.Parse(responseBodyAsText); } }

XDocument xmlDocument = await SomeAsyncCode.GetContentAsync();

// The Task will be started on call with await. ::

Dialects

Spec#

Spec# is a dialect of C# developed in parallel with the official implementation. It extends C# with specification language features and presents a possible future feature to the C# language. It adds syntax for the code contracts API that was introduced in .NET Framework 4.0. Spec# is developed by Microsoft Research.

This sample shows two of the basic structures that are used when adding contracts to code. ::code[lang=csharp] static void Main(string![] args) requires args.Length > 0 { foreach (string arg in args) {

}

} ::

  • is used to make a reference type non-nullable, e.g. it is not possible to set the value to null. This in contrast of nullable types which allow value types to be set as null.
  • 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

Spec# extends C# with non-nullable types that checks so the variables of nullable types that has been set as non-nullable are not null. If is null then an exception is thrown. ::code[lang=csharp] string! input ::

In use: ::code[lang=csharp] public Test(string! input) { ... } ::

Preconditions

Preconditions are checked before a method is executed. ::code[lang=csharp] public Test(int i) requires i > 0; { this.i = i; } ::

Postconditions

Postconditions are conditions that are ensured to be correct when a method has been executed. ::code[lang=csharp] public void Increment() ensures i > 0; { i++; } ::

Checked exceptions

Spec# adds checked exceptions like those in Java. ::code[lang=java] // SomeException extends ICheckedException public void DoSomething() throws SomeException { ... } ::

Checked exceptions may be inconvenient, 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. However, checked exceptions are designed to be immediately handled rather than continuously thrown up the stack.

References

  1. Bart de Smet on Spec#

References

  1. "C# Coding Conventions". Microsoft Learn.
  2. Wagner, Bill. "C# Keywords".
  3. (November 21, 2005). "C# for programmers".
  4. "C# Keywords".
  5. Wagner, Bill. "Integral numeric types".
  6. Wagner, Bill. "Floating-point numeric types".
  7. Wagner, Bill. "char".
  8. Wagner, Bill. "Strings and string literals".
  9. Wagner, Bill. "Declaration statements".
  10. Wagner, Bill. "Assignment operators".
  11. Wagner, Bill. "readonly".
  12. (2021-10-05). "Exploring C# 10: Save Space with File-Scoped Namespaces".
  13. [[#Archer. Archer]], Part 2, Chapter 4:The Type System
  14. "Generics (C# Programming Guide)". Microsoft.
  15. "An Introduction to C# Generics". Microsoft.
  16. "Differences Between C++ Templates and C# Generics". Microsoft.
  17. Microsoft MSDN]]
  18. ".NET Framework - What's New in C# 7.0".
  19. (April 15, 2016). "Thoughts on C# 7 Local Functions".
  20. Martin, Robert C.. (August 11, 2008). "Clean Code: A Handbook of Agile Software Craftsmanship". Prentice Hall International.

::callout[type=info title="Wikipedia Source"] This article was imported from Wikipedia and is available under the Creative Commons Attribution-ShareAlike 4.0 License. Content has been adapted to SurfDoc format. Original contributors can be found on the article history page. ::

c-sharp-(programming-language)programming-language-syntax