Shashi Penumarthy
Shashi Penumarthy

Reputation: 813

What is default and why is not overridable?

While performing code review, I found code that could cut down on potential bugs by using the Null object pattern. Then I began thinking: wouldn't it be useful if the default value of that business object was a null object instead of a null reference?

Since C# provides the default operator, I tried to overload it like this:

public static MyObject operator default (MyObject object) 
{
    return MyObject.Null;
}

That gives me the error: 'Overloadable unary operator expected'. On further digging, I found that one part of the docs says that default(T) is a Primary operator:Overloadable Operators.

And when you actually click on default(T) on the above page, it says default is a keyword.

On top of that, this page doesn't say that default is not overloadable: Overloadable Operators (C# Programming Guide).

I know this is kind of academic but I am trying to understand the language deeper. What is default(T)? Is it an operator or a keyword? And why is not overloadable (from a language design standpoint)?

UPDATE: Yes I've read C# language spec section 7.5.13 and I know what the language does. I am trying to understand why.

Upvotes: 18

Views: 4150

Answers (4)

Eric Lippert
Eric Lippert

Reputation: 660493

@codesinchaos' answer is basically spot on. A few additional thoughts.

Suppose you made an array of a thousand of your objects. Should every element of the newly-allocated array be initialized to your default value? Should the operator be invoked a thousand times?

What if the operator returns different values at different times?

What if the operator throws an exception?

In that scenario can a partially-initialized object be observed to be in a "pre-default-value" state?

Suppose MyObject.Null is a field. What is the value of the field before the default operator runs? Is that observable? Can you go into an infinite loop, trying to set MyObject.Null to its default value, which is MyObject.Null?

And so on. These are the sorts of questions language designers have to deal with when considering features like this. Most of the time, the solution is to not do the feature rather than try to figure out answers to all these tricky problems.

Thanks for pointing out that the documentation is deficient; I'll mention it to the documentation manager.

To answer your additional questions:

default is a reserved keyword of the C# language and has been since C# 1.0. The following are its usages in C#:

  1. The default operator is an operator whose argument must be the name of a type, like the typeof operator or the sizeof operator. This feature was added in C# 2.0 because it is handy when you have generics in the type system. Reference: default operator.

  2. The default literal: beginning with C# 7.1, you can use the default literal to produce the default value of a type when the compiler can infer the expression type. Reference: default literal.

  3. default can also be used to mark the default case of a switch statement.

  4. default can be used as part of a "preprocessor" directive.

Upvotes: 20

BrokenGlass
BrokenGlass

Reputation: 161002

Then I began thinking: wouldn't it be useful if the default value of that business object was a null object instead of a null reference?

It sounds like your project would benefit from using an IOC container that could inject a NullBusinessObject instance by default that does whatever you want it to do as default behavior. C# itself doesn't offer anything built in that you could override in this regard.

Upvotes: 2

agent-j
agent-j

Reputation: 27943

default(T) usually "zeros-out" creates a null reference for classes, and a zeroed out version of value types (struct in C#). default is a keyword in C# and an operator in MSIL. C# does not allow overriding of default.

Upvotes: 1

CodesInChaos
CodesInChaos

Reputation: 108880

Overloading default would complicate the design of C# and the runtime significantly. Currently it is assumed that the binary zeroing of any value type is valid and equivalent to default of that value type. And for references the null reference is always valid and equivalent to default of any reference type.

This allows the runtime to start running the constructors on an objects in a binary zero state and get sane behavior.

Upvotes: 15

Related Questions