C# – XML Documentation

XML Documentation

A documentation comment is a piece of embedded XML that documents a type or member. A documentation comment comes immediately before a type or member declaration and starts with three slashes, it can have single or multi line comments.

Standard XML Documentation Tags

<summary>…</summary> Indicates the tool tip that IntelliSense should display for the type or member;
typically a single phrase or sentence.
<remarks>…</remarks> Additional text that describes the type or member. Documentation generators
pick this up and merge it into the bulk of a type or member’s description.
<param name=”name”>…</param> Explains a parameter on a method.
<returns>…</returns> Explains the return value for a method.
<exception [cref=”type”]>…</exception> Lists an exception that a method may throw (cref refers to the exception
type).
<permission [cref=”type”]>…</permission> Indicates an IPermission type required by the documented type or member.
<example>…</example> Denotes an example using both text description and source code with <code> tag
<c>…</c> Indicates an inline code snippet usually inside an example block.
<code>…</code> Indicates a multiline code sample, usually inside example block
<see cref=”member”>…</see> Inserts an inline cross-reference to another type or member.
<seealso cref=”member”>…</seealso>> Cross-references another type or member.
<paramref name=”name”/> References a parameter from within a <summary> or <remarks> tag.
<list> Instructs documentation generators to emit a bulleted, numbered, or tablestyle
list.
<para>…</para> Instructs documentation generators to format the contents into a separate
paragraph.
<include file=’filename’ path=’tagpath[@name=”id”]’>…</include> Merges an external XML file that contains documentation. The path attribute denotes an XPath query to a specific element in that file.

User-Defined Tags

You are free to define your own tags.

Type or Member Cross-References

Type names and type or member cross-references are translated into IDs that uniquely define the type or member.

These names are composed of a prefix that defines what the ID represents and a signature of the type or member.

N Namespace
T Type (class, struct, enum, interface, delegate)
F Field
P Property (includes indexers)
M Method (includes special methods)
E Event
! Error

C# – Preprocessor Directives

Preprocessor Directives

Preprocessor directives supply the compiler with additional information about regions of code.

The most common preprocessor directives are the conditional directives, which provide a way to include or exclude regions of code from compilation.

In this class, the statement in Foo is compiled as conditionally dependent upon the presence of the DEBUG symbol.

#define DEBUG
class MyClass
{
  int x;
  void Foo()
  {
     #if DEBUG
     Console.WriteLine("Testing: x = {0}", x);
     #endif
  }
  ...
}
#define symbol Defines symbol
#undef symbol Undefines symbol
#if symbol [operator symbol2]… symbol to test
operators are ==, !=, &&, and || followed by #else, #elif, and #endif
#else Executes code to subsequent #endif
#elif symbol [operator symbol2] Combines #else branch and #if test
#endif Ends conditional directives
#warning text text of the warning to appear in compiler output
#error text text of the error to appear in compiler output
#pragma warning [disable | restore] Disables/restores compiler warning(s)
#line [ number [“file”] | hidden] number specifies the line in source code; file is the filename to appear in computer output; hidden instructs debuggers to skip over code from this point until the next #line directive.
#region name Marks the beginning of an outline
#endregion Ends an outline region

Conditional Attributes

An attribute decorated with the Conditional attribute will be compiled only if a given preprocessor symbol is present.

//file1.cs
#define DEBUG
using System;
using System.Diagnostics;
[Conditional("DEBUG")]
public class TestAttribute : Attribute {}

//file2.cs
#define DEBUG
[Test]
class Foo
{
  [Test]
  string s;
}

The compiler will only incorporate the [Test] attributes if the DEBUG symbol is in
scope for file2.cs.

Pragma Warning

The compiler generates a warning when it spots something in your code that seems
unintentional but it does not prevent the code from compiling.

Compiler warnings can be extremely valuable in spotting bugs.

Pragma Warning is used to suppress warning. Omitting the number in the #pragma warning directive disables or restores all warning codes.

public class Foo
{
	static void Main() {}

	#pragma warning disable 414
	static string Message = "Hello";
	#pragma warning restore 414
}

C# – Unsafe Code and Pointers

Unsafe Code and Pointers

C# supports direct memory manipulation via pointers within blocks of code marked unsafe and compiled with the /unsafe compiler option.

Pointer Basics

A pointer instance holds the address of a variable. Pointer types can be (unsafely) cast to any other pointer type.

& The address-of operator returns a pointer to the address of a variable
* The dereference operator returns the variable at the address of a pointer
-> The pointer-to-member operator is a syntactic shortcut, in which x->y is equivalent to (*x).y

Unsafe Code

Using the keyword unsafe for a type, type member or statement block, you are permitted to use pointer types and perform C++ style pointer operations on memory within that scope.

// C# supports direct memory manipulation via pointers within blocks of code marked unsafe
// and compiled with the /unsafe compiler option. LINQPad implicitly compiles with this option.

// Here's how to use pointers to quickly process a bitmap:

unsafe static void BlueFilter (int[,] bitmap)
{
  int length = bitmap.Length;
  fixed (int* b = bitmap)
  {
	int* p = b;
	for (int i = 0; i < length; i++)
	  *p++ &= 0xFF;
  }
}

static void Main()
{
	int[,] bitmap = { {0x101010, 0x808080, 0xFFFFFF}, {0x101010, 0x808080, 0xFFFFFF} };
	BlueFilter (bitmap);
	bitmap.Dump();
}

The Fixed Statement

The fixed statement is required to pin a managed object so that the garbage collector can pin the object and not move it around.

Within a fixed statement, you can get a pointer to any value type, an array of value types, or a string. In the case of arrays and strings, the pointer will actually point to the first element, which is a value type.

// Value types declared inline within reference types require the reference type to be pinned:

class Test
{
	public int X;
}

static void Main()
{
	Test test = new Test();
	unsafe
	{
	   fixed (int* p = &test.X)   // Pins test
	   {
		 *p = 9;
	   }
	   Console.WriteLine (test.X);
	}	
}

The Pointer-to-Member Operator

// In addition to the & and * operators, C# also provides the C++ style -> operator,
// which can be used on structs:

struct Test
{
	public int X;
}

unsafe static void Main()
{
	Test test = new Test();
	Test* p = &test;
	p->X = 9;
	Console.WriteLine (test.X);
}

Arrays

The stackalloc keyword

// Memory can be allocated in a block on the stack explicitly using the stackalloc keyword:

unsafe
{
	int* a = stackalloc int [10];
	for (int i = 0; i < 10; ++i)
		Console.WriteLine (a[i]);   // Print raw memory
}

Fixed-size buffers

// Memory can be allocated in a block within a struct using the fixed keyword:

unsafe struct UnsafeUnicodeString
{
	public short Length;
	public fixed byte Buffer[30];
}

unsafe class UnsafeClass
{
	UnsafeUnicodeString uus;
	public UnsafeClass (string s)
	{
		uus.Length = (short)s.Length;
		fixed (byte* p = uus.Buffer)
		for (int i = 0; i < s.Length; i++)
			p[i] = (byte) s[i];
	}
}

static void Main() { new UnsafeClass ("Christian Troy"); }

void*

// A void pointer (void*) makes no assumptions about the type of the underlying data and is
// useful for functions that deal with raw memory:
//A void* cannot be dereferenced, and arithmetic operations cannot be performed on void pointers.
unsafe static void Main()
{
	short[] a = {1,1,2,3,5,8,13,21,34,55};
	fixed (short* p = a)
	{
		//sizeof returns size of value-type in bytes
		Zap (p, a.Length * sizeof (short));
	}
	foreach (short x in a)
		System.Console.WriteLine (x);   // Prints all zeros
}

unsafe static void Zap (void* memory, int byteCount)
{
	byte* b = (byte*) memory;
		for (int i = 0; i < byteCount; i++)
			*b++ = 0;
}

C# – Attributes

Attributes

Attributes are an extensible mechanism for adding custom information to code elements (assemblies, types, members, return values, parameters, and generic type parameters).

This extensibility is useful for services that integrate deeply into the type system, without requiring special keywords or constructs in the C# language.

Example:
serialization – the process of converting arbitrary objects to and from a particular format.

Attribute Classes

Attribute defined by a class inherits from abstract class System.Attribute.

To attach an attribute to a code element, specify the attribute’s type name in square brackets, before the code element.

[ObsoleteAttribute]
public class Foo { ... }

This attribute is recognized by the compiler and will cause compiler warnings if a type or member marked obsolete is referenced.

Named and Positional Attribute Parameters

Attributes may have parameters.

The following attribute maps the CustomerEntity class to an XML element named Customer, belonging to the http://oreilly.com namespace.

[XmlElement ("Customer", Namespace="http://oreilly.com")]
public class CustomerEntity { ... }

Attribute parameters fall into one of two categories: positional or named. The first argument is a positional parameter and second is a named parameter.

Positional parameters correspond to parameters of the attribute type’s public constructors. You must include positional parameters that correspond to one of the attribute’s constructors.

Named parameters correspond to public fields or public properties on the attribute type and it is optional.

Attribute Targets

Implicitly, the target of an attribute is the code element it immediately precedes, which is typically a type or type member.

Example of using the CLSCompliant attribute to specify CLS compliance for an entire assembly.

[assembly:CLSCompliant(true)]

Specifying Multiple Attributes

Multiple attributes can be specified for a single code element.

Each attribute can be listed either within the same pair of square brackets (separated by a comma) or in separate pairs of square brackets (or a combination of the two).

[Serializable, Obsolete, CLSCompliant(false)]
public class Bar {...}
[Serializable] [Obsolete] [CLSCompliant(false)]
public class Bar {...}
[Serializable, Obsolete]
[CLSCompliant(false)]
public class Bar {...}

Caller Info Attributes (C# 5)

From C# 5, you can tag optional parameters with one of three caller info attributes, which instruct the compiler to feed information obtained from the caller’s source code into the parameter’s default value:

[CallerMemberName] applies the caller’s member name

[CallerFilePath] applies the path to caller’s source code file

[CallerLineNumber] applies the line number in caller’s source code file

using System.Runtime.CompilerServices;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           Foo();
        }
        
        static void Foo (
	[CallerMemberName] string memberName = null,
	[CallerFilePath] string filePath = null,
	[CallerLineNumber] int lineNumber = 0)
{
	Console.WriteLine (memberName);
	Console.WriteLine (filePath);
	Console.WriteLine (lineNumber);
}
    }   
   
}

Output:
Main
c:\Windows\Temp\dlexntz1.0.cs
16

Caller info attributes are useful for logging—and for implementing patterns such as firing a single change notification event whenever any property on an object changes.

INotifyPropertyChanged in System.ComponentModel

public interface INotifyPropertyChanged
{
    event PropertyChangedEventHandler PropertyChanged;
}
public delegate void PropertyChangedEventHandler
(object sender, PropertyChangedEventArgs e);

public class PropertyChangedEventArgs : EventArgs
{
    public PropertyChangedEventArgs (string propertyName);
    public virtual string PropertyName { get; }
}

By applying the [CallerMemberName] attribute, however, it implement this interface and invoke the event without ever specifying property names

public class Foo : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged = delegate { };
   void RaisePropertyChanged ([CallerMemberName] string propertyName = null)
   {
      PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
   }
   string customerName;
   public string CustomerName
   {
      get { return customerName; }
      set
      {
          if (value == customerName) return;
          customerName = value;
          RaisePropertyChanged();
          // The compiler converts the above line to:
          // RaisePropertyChanged ("CustomerName");
      }
   }
}

C# – Anonymous Types

Anonymous Types

Anonymous type is a simple class created by the compiler on the fly to store a set of values.

It is created using the new keyword followed by an object initializer, specifying the properties and values.

You must use the var keyword to reference an anonymous type.

Anonymous types are used mostly when writing LINQ queries.

var dude = new {Name = "Bob", Age = 23};

compiler compiles into:

internal class AnonymousGeneratedTypeName
{
	private string name; // Actual field name is irrelevant
	private int age; // Actual field name is irrelevant

	public AnonymousGeneratedTypeName (string name, int age)
	{
		this.name = name; this.age = age;
	}

	public string Name { get { return name; } }

	public int Age { get { return age; } }


	// The Equals and GetHashCode methods are overridden (see Chapter 6).
	// The ToString method is also overridden.
}
...
var dude = new AnonymousGeneratedTypeName ("Bob", 23);

The property name of an anonymous type can be inferred from an expression that is itself an identifier (or ends with one).

int Age = 23;

// The following:
{
	var dude = new { Name = "Bob", Age, Age.ToString().Length };
	dude.Dump();
}
// is shorthand for:
{
	var dude = new { Name = "Bob", Age = Age, Length = Age.ToString().Length };
	dude.Dump();
}

Two anonymous type instances will have the same underlying type if their elements are same-typed and they’re declared within the same assembly.

var a1 = new { X = 2, Y = 4 };
var a2 = new { X = 2, Y = 4 };
Console.WriteLine (a1.GetType() == a2.GetType());   // True

// Additionally, the Equals method is overridden to perform equality comparisons:

Console.WriteLine (a1 == a2);         // False
Console.WriteLine (a1.Equals (a2));   // True

You can create arrays of anonymous types

var dudes = new[]
{
   new {Name = "Bob", Age = 30},
   new {Name = "Tom", Age = 40}
}

C# – New

New Operator/Modifier/Constraint

new keyword can be used for operator, modifier, constraint.

New Operator

1. Is used to create objects and invoke constructors.

Class1 obj = new Class1();

2. Used to create instances of anonymous types.

var query = from cust in customers  
            select new { Name = cust.Name, Address = cust.PrimaryAddress }; 

3. Is used to invoke default constructor.

int i = new int();
//equivalent to 
int i = 0;

Note:

  • Do not declare default constructor of struct because every type implicitly has a public default constructor.
  • It is possible to declare parameterized constructors on a struct type to set its initial values.
  • Types such as files handles, network connection it is recommended to use using statement to cleanup the resources.
  • New operator cannot be overloaded.

New Modifier

  • Hides a member that is inherited from a base class.
  • Derived version overrides the base class version.
  • You can hide without new keyword but with new modifier it suppressed the warning.
public class BaseC
{
	public it x;
	public void Invoke() {}
}

public class Derived : BaseC
{
	new public void Invoke() {}
}

Note:

  • Constants, fields, properties or type introduced in class or struct sharing the same name hides the base class members.
  • A method introduced in a class or struct hides properties, fields, and types that share that name in the base class.
  • An indexer introduced in a class or struct hides all base class indexers that have the same signature.
  • It is an error to use both new and override on the same member, because both have mutually same meaning. New creates new member, override extends the implementation.

New Constraints (Generic)

The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor.

To use the new constraint, the type cannot be abstract.

Apply the new constraint to a type parameter when your generic class creates new instances of the type, as shown in the following example:

class ItemFactory where T : new()
{
    public T GetNewItem()
    {
        return new T();
    }
}

When you use the new() constraint with other constraints, it must be specified last:

public class ItemFactory2
    where T : IComparable, new()
{
}

C# – Command Prompt

Using Visual Studio Command Prompt

Compiling files togehter
csc /t:exe /out:MyProgram.exe MyMainClass.cs MyClass.cs

or

csc /t:exe /out:MyProgram.exe *.cs

C# – List of Articles

List of Articles

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z

C# – Extension Methods

Extension Methods

Allow existing type to be extended with new methods without altering the definition of the original type.

An extension method is a static method of a static class, where modifier is applied to the first parameter.

// Extension methods allow an existing type to be extended with new methods without altering
// the definition of the original type:

// (Note that these examples will not work in older versions of LINQPad)

static void Main()
{
	Console.WriteLine ("Perth".IsCapitalized());	
	// Equivalent to:
	Console.WriteLine (StringHelper.IsCapitalized ("Perth"));	
	
	// Interfaces can be extended, too:
	Console.WriteLine ("Seattle".First());   // S
}

public static class StringHelper
{
	public static bool IsCapitalized (this string s)
	{
		if (string.IsNullOrEmpty(s)) return false;
		return char.IsUpper (s[0]);
	}
	
	public static T First<T> (this IEnumerable sequence)
	{
		foreach (T element in sequence)
			return element;
		
		throw new InvalidOperationException ("No elements!");
	}
}

Extension Method Chaining

// Extension methods, like instance methods, provide a tidy way to chain functions:

static void Main()
{
	string x = "sausage".Pluralize().Capitalize();
	x.Dump();
	
	// Equivalent to:
	string y = StringHelper.Capitalize (StringHelper.Pluralize ("sausage"));
	y.Dump();
	
	// LINQPad's Dump method is an extension method:
	"sausage".Pluralize().Capitalize().Dump();
}

public static class StringHelper
{
	public static string Pluralize (this string s) => s + "s";   // Very naiive implementation!
	
	public static string Capitalize (this string s) => s.ToUpper();
}

Ambiguity and Resolution

Namespaces

An extension method cannot be accessed unless its class is in scope, by importing its namespace.

using System;

namespace Utils
{
   public static class StringHelper
   {
      public static bool IsCapitalized (this string s)
      {
         if(string.IsNullOrEmpty(s)) return false;
         return char.IsUpper(s[0]);
      }
   }
}

To use IsCapitalized, need to import Utils namespace

namespace MyApp
{
   using Utils;
   class Test
   {
      static void Main() => Console.WriteLine ("Perth".IsCapitalized());
   }
}

Extension methods versus instance methods

// Any compatible instance method will always take precedence over an extension method:

static void Main()
{
	new Test().Foo ("string");	// Instance method wins, as you'd expect
	new Test().Foo (123);		// Instance method still wins
}

public class Test
{
	public void Foo (object x) { "Instance".Dump(); }    // This method always wins
}

public static class StringHelper
{
	public static void Foo (this UserQuery.Test t, int x) { "Extension".Dump(); }
}

Extension methods versus extension methods

// The extension method with more specific arguments wins. Classes & structs are
// considered more specific than interfaces:

static void Main()
{
	"Perth".IsCapitalized().Dump();
}

static class StringHelper
{
	public static bool IsCapitalized (this string s)
	{
		"StringHelper.IsCapitalized".Dump();
		return char.IsUpper (s[0]);
	}
}

static class EnumerableHelper
{
	public static bool IsCapitalized (this IEnumerable s)
	{
		"Enumerable.IsCapitalized".Dump();
		return char.IsUpper (s.First());
	}
}
// The extension method with more specific arguments wins. Classes & structs are
// considered more specific than interfaces:

static void Main()
{
	string[] strings = { "a", "b", null, "c"};
	foreach (string s in strings.StripNulls())
		Console.WriteLine (s);
}

static class Test
{
	public static IEnumerable StripNulls (this IEnumerable seq)
	{
		foreach (T t in seq)
			if (t != null)
				yield return t;
	}
}

C# – Operator Overloading

Operator Overloading

Operators can be overloaded to provide more natural syntax for custom types.

The following operators can be overloaded:

+ (unary) – (unary) ! ~ ++
+ * /
% & | ^ <<
>> == != > <
>= <=

The following operators are also overloadable:

  • Implicit and explicit conversions
  • The true and false operators

The following operators are indirectly overloaded:

  • The compound assignment operators (e.g., +=, /=) are implicitly overridden by overriding the noncompound operators (e.g., +, /).
  • The conditional operators && and || are implicitly overridden by overriding the bitwise operators & and |.

Operator Functions

The operator is overloaded be declaring an operator function.

Operator function rules:

  • The name of the function is specified with the operator keyword followed by an operator symbol.
  • The operator function must be marked static and public.
  • The parameters of the operator function represent the operands.
  • The return type of an operator function represents the result of an expression.
  • At least one of the operands must be the type in which the operator function is declared.
//define struct Note representing a musical note and then overload the + operator.
public struct Note
{
	int value;
	public int SemitonesFromA => value;
	
	public Note (int semitonesFromA) { value = semitonesFromA; }

	public static Note operator + (Note x, int semitones)
	{
		return new Note (x.value + semitones);
	}
	
	// Or more tersely:
	// public static Note operator + (Note x, int semitones) => new Note (x.value + semitones);
	
	// See the last example in "Equality Comparison", Chapter 6 for an example of overloading the == operator
}

static void Main()
{
	//allows to add int to Note
        Note B = new Note (2);
	Note CSharp = B + 2;	
	CSharp.SemitonesFromA.Dump();
	
	//automatically overloads the corresponding compound assignment operator
        CSharp += 2;	
	CSharp.SemitonesFromA.Dump();
}

Overloading Equality and Comparison Operators

Equality and comparison operators are sometimes overridden when writing structs and classes.

Rules:
Pairing

The C# compiler enforces operators that are logical pairs to both be defined. These operators are (== notequal) (< >) (<= >=).

Equals and GetHashCode

When overloading (==) and (notequal) the Equals and GetHashCode methods defined in the object class needs to be overridden.

IComparable and IComparable<T>

If you overload (< >) and (<= >=), you should implement IComparable and IComparable<T>.

Custom Implicit and Explicit Conversions

Implicit and explicit conversions are overloadable operators.

The conversions are overloaded to make converting between strongly types concise and natural.

To convert weakly types:

Write a constructor that has a parameter of the type to convert from.

Write ToXXX and (static) FromXXX methods to convert between types.

// Implicit and explicit conversions are overloadable operators:

public struct Note
{
	int value;
	public int SemitonesFromA { get { return value; } }
	
	public Note (int semitonesFromA) { value = semitonesFromA; }

	// Convert to hertz
	public static implicit operator double (Note x) =>  440 * Math.Pow (2, (double) x.value / 12 );
	
	// Convert from hertz (accurate to the nearest semitone)
	public static explicit operator Note (double x) => new Note ((int) (0.5 + 12 * (Math.Log (x/440) / Math.Log(2) ) ));
}

static void Main()
{
	Note n = (Note)554.37;  // explicit conversion
	double x = n;           // implicit conversion
	x.Dump();	
}

Overloading true and false

// The true and false operators are overloaded in the extremely rare case of types that
// are boolean “in spirit”, but do not have a conversion to bool.

// An example is the System.Data.SqlTypes.SqlBoolean type which is defined as follows:

public struct SqlBoolean
{
	public static bool operator true (SqlBoolean x) => x.m_value == True.m_value;
	
	public static bool operator false (SqlBoolean x) => x.m_value == False.m_value;
	
	public static SqlBoolean operator ! (SqlBoolean x)
	{
		if (x.m_value == Null.m_value)  return Null;
		if (x.m_value == False.m_value) return True;
		return False;
	}
	
	public static readonly SqlBoolean Null =  new SqlBoolean(0);
	public static readonly SqlBoolean False = new SqlBoolean(1);
	public static readonly SqlBoolean True =  new SqlBoolean(2);
	
	SqlBoolean (byte value) { m_value = value; }
	byte m_value;
}


static void Main()
{
	SqlBoolean a = SqlBoolean.Null;
	if (a)
		Console.WriteLine ("True");
	else if (!a)
		Console.WriteLine ("False");
	else
		Console.WriteLine ("Null");	
}