Skip to content

Instantly share code, notes, and snippets.

@DevWouter
Last active November 9, 2021 22:32
Show Gist options
  • Save DevWouter/b72424406aa0d813050a6f5b826177c2 to your computer and use it in GitHub Desktop.
Save DevWouter/b72424406aa0d813050a6f5b826177c2 to your computer and use it in GitHub Desktop.
using System;
namespace Dummy
{
class Program
{
private static void Header(string title)
{
Console.WriteLine(new string('=', 79));
Console.WriteLine(title);
Console.WriteLine(new string('=', 79));
}
static void Main()
{
WrapValue<string>.DefaultValue = "missing-name";
var withValue = new WrapValue<string>("Wouter");
var withoutValue = new WrapValue<string>();
Header("Without handling");
Console.WriteLine("My name is {0}", withValue);
Console.WriteLine("My name is {0}", withoutValue);
Header("With handling");
WrapValue<string>.MissingValueHandler = _ =>
Console.WriteLine("WARNING: Returning default value because no actual value");
Console.WriteLine("My name is {0}", withValue);
Console.WriteLine("My name is {0}", withoutValue);
try
{
Header("With exception management");
WrapValue<string>.MissingValueHandler = _ =>
throw new Exception($"Returning default value because no actual value");
Console.WriteLine("My name is {0}", withValue);
Console.WriteLine("My name is {0}", withoutValue);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex);
}
// The downsides:
// 1. The MissingValueHandler and Default value are static to the type and not the field but that can easily
// by providing a parent and a type name.
// 2. This approach hides things from the developer that uses it, making it harder to debug (and I don't like that)
}
public class WrapValue<T>
{
public bool HasValue { get; }
public T ActualValue { get; }
public static T DefaultValue { get; set; }
public static Action<WrapValue<T>> MissingValueHandler { get; set; } = _ => { };
public WrapValue(T value)
{
ActualValue = value;
HasValue = true;
}
public WrapValue()
{
HasValue = false;
}
public static implicit operator WrapValue<T>(T value)
{
return new WrapValue<T>(value);
}
public static implicit operator T(WrapValue<T> d)
{
if (d.HasValue)
{
return d.ActualValue;
}
MissingValueHandler(d);
return DefaultValue;
}
public override string ToString()
{
// ReSharper disable once RedundantCast because it's not redundant since we don't want "WrapValue`1[T]"
return ((T)this).ToString();
}
}
}
}
@DevWouter
Copy link
Author

Output:

===============================================================================
Without handling
===============================================================================
My name is Wouter
My name is missing-name
===============================================================================
With handling
===============================================================================
My name is Wouter
WARNING: Returning default value because no actual value
My name is missing-name
===============================================================================
With exception management
===============================================================================
My name is Wouter
Exception: System.Exception: Returning default value because no actual value
   at Dummy.Program.<>c.<Main>b__1_1(WrapValue`1 _) in C:\repos\Dummy\Dummy\Prog
ram.cs:line 35
   at Dummy.Program.WrapValue`1.op_Implicit(WrapValue`1 d) in C:\repos\Dummy\Dum
my\Program.cs:line 80
   at Dummy.Program.WrapValue`1.ToString() in C:\repos\Dummy\Dummy\Program.cs:li
ne 87
   at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, Str
ing format, ParamsArray args)
   at System.IO.StreamWriter.WriteFormatHelper(String format, ParamsArray args,
Boolean appendNewLine)
   at System.IO.StreamWriter.WriteLine(String format, Object arg0)
   at System.IO.TextWriter.SyncTextWriter.WriteLine(String format, Object arg0)
   at System.Console.WriteLine(String format, Object arg0)
   at Dummy.Program.Main() in C:\repos\Dummy\Dummy\Program.cs:line 37

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment