Steps are the same in C#, it's just about different syntax and language features. So considering the following steps:
- Create the abstract class or interface or your object
- Create concrete implementation
- Create the null implementation by overriding the methods and returning proper values for the null object
You can see an example following above steps to implement Null Object pattern in C#, but before jumping to the example, you may want to learn more about the following C# language features which may help you avoid null exceptions:
-
??
and??=
Null-coalescing and null-coalescing assignment operators -
?.
and?[]
Null-conditional operators - Nullable reference types
Example C# Null Object Pattern
Here is the interface for animal:
public interface IAnimal
{
string GetName();
string MakeSound();
}
And two concrete implementations, for duck and cat:
public class Duck : IAnimal
{
public string GetName()
{
return "Duck";
}
public string MakeSound()
{
return "Quack quack!";
}
}
public class Cat : IAnimal
{
public string GetName()
{
return "Cat";
}
public string MakeSound()
{
return "Meow meow!";
}
}
Now I'll implement the null object as a singleton:
public sealed class NullAnimal : IAnimal
{
private static readonly IAnimal nullAnimal = new NullAnimal();
private NullAnimal() { }
public string MakeSound()
{
return string.Empty;
}
public string GetName()
{
return String.Empty;
}
public static IAnimal Instance
{
get
{
return nullAnimal;
}
}
}
Then I'll create a factory to return the animal, based on the name:
public class AnimalFactory
{
public static IAnimal GetAnimal(string name)
{
if (name == "duck")
return new Duck();
else if (name == "cat")
return new Cat();
else
return NullAnimal.Instance;
}
}
And the usage:
var animals = new[] { "duck", "cat", "unknown" };
foreach (var name in animals)
{
var animal = AnimalFactory.GetAnimal(name);
Console.WriteLine($"{animal.GetName()} says: {animal.MakeSound()}");
}
Which returns:
Duck says: Quack quack!
Cat says: Meow meow!
says: