default value expressions (C# programming guide)

A default value expression default(T) produces the default value of a type T. The following table shows which values are produced for various types:

Type Default value
Any reference type null
Numeric value type Zero
bool false
char '\0'
enum The value produced by the expression (E)0, where E is the enum identifier.
struct The value produced by setting all value type fields to their default value and all reference type fields to null.
Nullable type An instance for which the HasValue property is false and the Value property is undefined.

Default value expressions are particularly useful in generic classes and methods. One issue that arises using generics is how to assign a default value of a parameterized type T when you don't know the following in advance:

  • Whether T is a reference type or a value type.
  • If T is a value type, whether it's a numeric value or a struct.

Given a variable t of a parameterized type T, the statement t = null is only valid if T is a reference type. The assignment t = 0 only works for numeric value types but not for structs. To solve that, use a default value expression:

T t = default(T);

The default(T) expression is not limited to generic classes and methods. Default value expressions can be used with any managed type. Any of these expressions are valid:

var s = default(string);
var d = default(dynamic);
var i = default(int);
var n = default(int?); // n is a Nullable int where HasValue is false.

The following example from the GenericList<T> class shows how to use the default(T) operator in a generic class. For more information, see Introduction to Generics.

namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            // Test with a non-empty list of integers.
            GenericList<int> gll = new GenericList<int>();
            int intVal = gll.GetLast();
            // The following line displays 5.

            // Test with an empty list of integers.
            GenericList<int> gll2 = new GenericList<int>();
            intVal = gll2.GetLast();
            // The following line displays 0.

            // Test with a non-empty list of strings.
            GenericList<string> gll3 = new GenericList<string>();
            string sVal = gll3.GetLast();
            // The following line displays five.

            // Test with an empty list of strings.
            GenericList<string> gll4 = new GenericList<string>();
            sVal = gll4.GetLast();
            // The following line displays a blank line.

    // T is the type of data stored in a particular instance of GenericList.
    public class GenericList<T>
        private class Node
            // Each node has a reference to the next node in the list.
            public Node Next;
            // Each node holds a value of type T.
            public T Data;

        // The list is initially empty.
        private Node head = null;

        // Add a node at the beginning of the list with t as its data value.
        public void AddNode(T t)
            Node newNode = new Node();
            newNode.Next = head;
            newNode.Data = t;
            head = newNode;

        // The following method returns the data value stored in the last node in
        // the list. If the list is empty, the default value for type T is
        // returned.
        public T GetLast()
            // The value of temp is returned as the value of the method. 
            // The following declaration initializes temp to the appropriate 
            // default value for type T. The default value is returned if the 
            // list is empty.
            T temp = default(T);

            Node current = head;
            while (current != null)
                temp = current.Data;
                current = current.Next;
            return temp;

default literal and type inference

Beginning with C# 7.1, the default literal can be used for default value expressions when the compiler can infer the type of the expression. The default literal produces the same value as the equivalent default(T) where T is the inferred type. This can make code more concise by reducing the redundancy of declaring a type more than once. The default literal can be used in any of the following locations:

  • variable initializer
  • variable assignment
  • declaring the default value for an optional parameter
  • providing the value for a method call argument
  • return statement (or expression in an expression bodied member)

The following example shows many usages of the default literal in a default value expression:

public struct Point
    public double X { get; }
    public double Y { get; }

    public Point(double x, double y)
        X = x;
        Y = y;

public class LabeledPoint
    public double X { get; private set; }
    public double Y { get; private set; }
    public string Label { get; set; }

    // Providing the value for a default argument:
    public LabeledPoint(double x, double y, string label = default)
        X = x;
        Y = y;
        Label = label;

    public static LabeledPoint MovePoint(LabeledPoint source, 
        double xDistance, double yDistance)
        // return a default value:
        if (source == null)
            return default;

        return new LabeledPoint(source.X + xDistance, source.Y + yDistance, 

    public static LabeledPoint FindClosestLocation(IEnumerable<LabeledPoint> sequence, 
        Point location)
        // initialize variable:
        LabeledPoint rVal = default;
        double distance = double.MaxValue;

        foreach (var pt in sequence)
            var thisDistance = Math.Sqrt((pt.X - location.X) * (pt.X - location.X) +
                (pt.Y - location.Y) * (pt.Y - location.Y));
            if (thisDistance < distance)
                distance = thisDistance;
                rVal = pt;

        return rVal;

    public static LabeledPoint ClosestToOrigin(IEnumerable<LabeledPoint> sequence)
        // Pass default value of an argument.
        => FindClosestLocation(sequence, default);

See also