Skip to content

Instantly share code, notes, and snippets.

@bradphelan
Created July 16, 2014 13:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradphelan/26c0e84197092620359a to your computer and use it in GitHub Desktop.
Save bradphelan/26c0e84197092620359a to your computer and use it in GitHub Desktop.
Type system abuse to simulate dependent types in C#
public interface IDigit {
int Value { get; }
}
public class _0 : IDigit { public int Value { get { return 0;} } }
public class _1 : IDigit { public int Value { get { return 1;} } }
public class _2 : IDigit { public int Value { get { return 2;} } }
public class _3 : IDigit { public int Value { get { return 3;} } }
public interface ILength {
int Value { get; }
}
public class Length<T0> : ILength
where T0 : IDigit, new()
{
public int Value
{
get
{
return new T0().Value;
}
}
}
public class Length<T1,T0> : ILength where T0 : IDigit, new() where T1 : IDigit, new()
{
public int Value
{
get
{
return new T1().Value*10 + new T0().Value;
}
}
}
public class Length<T2, T1, T0> : ILength
where T0 : IDigit, new()
where T1 : IDigit, new()
where T2 : IDigit, new()
{
public int Value
{
get
{
return new T2().Value*100 + new T1().Value*10 + new T0().Value;
}
}
}
public class String<TLength> where TLength : ILength, new() {
public int _MaxLength;
public String(){
_MaxLength = new TLength().Value;
}
}
public void LengthCheck(String<Length<_3, _1, _2>> s312)
{
Console.WriteLine(s312._MaxLength);
}
[Fact]
public void FactMethodName()
{
var s312 = new String<Length<_3, _1, _2>>();
var s313 = new String<Length<_3, _1, _3>>();
// Passes
s312._MaxLength.Should().Be(312);
// Type checks
LengthCheck(s312);
// Fails to type check
LengthCheck(s313);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment