Implementing multiparameter C++ template like behaviour on C# using Policy Pattern - c#

I'm trying to implement a c++ like template with C# generics and policy pattern based on this answer
This is a sample of the pattern:
interface ISomePolicy<T,U>
{
void _doSomething(U u);
}
class MyClass<T,U>:
ISomePolicy<int, double>,
ISomePolicy<int, int>
{
internal T myElement {get;set;}
public MyClass(T Element) {
myElement = Element;
}
void ISomePolicy<int, double>._doSomething(double u)
{
Console.WriteLine("this is int, double");
}
void ISomePolicy<int, int>._doSomething(int u)
{
Console.WriteLine("this is int, int");
}
}
static class MyClassExtension
{
//What I want to do
public static void doSomething<P, T, U>(this P oTh, U u) where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
}
My intended behaviour is like this:
MyClass<int, double> oClass = new MyClass<int, double>(3);
oClass.doSomething(0.5); //This works
oClass.doSomething(1); //This works
oClass.doSomething("This should fail"); //Breaks at compile time
MyClass<string, double> oClass1 = new MyClass<string, double>("sadfsd"); //Not implemented, wasn't able to prevent the construction.
oClass1.doSomething(0.4); //Breaks at compile time
But so far I wasn't able to make .net accept Generic Extension with less arguments than parameters
I can call the interface explicitly, which is horrible verbose defeating the purpose of all this.
oClass.doSomething < MyClass<int, double>,int,double>(0.5);
I thought of working that around with a wrapper:
static class MyClassExtension{
private static void wrappedDoSomething<P, T, U>(this P oTh, U u)
where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
public static void doSomething<T, U>(this MyClass<T, U> oTh, U u)
{
oTh.wrappedDoSomething<MyClass<T, U>, T, U>(u);
}
}
But the wrapper can't resolve both types for the wrapped function, failing with:
Error 1 The type 'MyClass' cannot be used as type parameter 'P'
in the generic type or method
'MyClassExtension.wrappedDoSomething(P, U)'. There is no
implicit reference conversion from 'MyClass' to
'ISomePolicy'
Any insights to fix the parameters issue or redesign all this are appreciated.
For context this would be used to wrap I/O translators. T in my case would be the target I/O format, and U the object representation of that data used by my framework.
I'm aware that this can be easily achieved with delegates or interfaces, but the objective is that the framework user easily instantiates the desired translation, and if an implementation doesn't exists, it can be trivially added to a common interface.
EDIT: Resolving a generic method from inside another generic method/class neither seems to work on mono.

Usually, policies should not contain data. For example,
interface ISomePolicy<T, U>
{
void _doSomething(T t, U u);
}
struct SomePolicyImplementation :
ISomePolicy<int, double>,
ISomePolicy<int, int>,
ISomePolicy<double, double>
{
void ISomePolicy<int, int>._doSomething(int t, int u)
=> Console.WriteLine("this is int, int");
void ISomePolicy<int, double>._doSomething(int t, double u)
=> Console.WriteLine("this is int, double");
void ISomePolicy<double, double>._doSomething(double t, double u)
=> Console.WriteLine("this is double, double");
}
static class SomePolicyExtension
{
public static void doSomething<P, T, U>(this P policy, T t, U u)
where P : struct, ISomePolicy<T, U>
=> policy._doSomething(t, u);
}
If you would like to combine policies and data then you may consider different interface
interface IEmbeddedPolicy<U>
{
void _doSomething(U u);
}
class MyClass<T> :
IEmbeddedPolicy<double>,
IEmbeddedPolicy<int>
{
public T Value { get; }
public MyClass(T value) { this.Value = value; }
void IEmbeddedPolicy<int>._doSomething(int u)
=> Console.WriteLine("this is T, int");
void IEmbeddedPolicy<double>._doSomething(double u)
=> Console.WriteLine("this is T, double");
}
static class EmbeddedPolicyExtension
{
public static void doSomething<E, U>(this E embedded, U u)
where E : IEmbeddedPolicy<U>
=> embedded._doSomething(u);
}
Or combination of these two concepts
class MySuperClass<P, T>:
IEmbeddedPolicy<double>,
IEmbeddedPolicy<int>
where P: struct, ISomePolicy<T, double>, ISomePolicy<T, int>
{
public T Value { get; }
public MySuperClass(T value) { this.Value = value; }
void IEmbeddedPolicy<int>._doSomething(int u)
=> new P()._doSomething(this.Value, u);
void IEmbeddedPolicy<double>._doSomething(double u)
=> new P()._doSomething(this.Value, u);
}
Usage:
// independent policy
var policy = new SomePolicyImplementation();
policy.doSomething(5, 6);
policy.doSomething(5, 6.7);
policy.doSomething(5.3, 6.7);
// embedded policy
var my = new MyClass<int>(54);
my.doSomething(5);
my.doSomething(89.7);
// combination
var x = new MySuperClass<SomePolicyImplementation, int>(53);
x.doSomething(9);
x.doSomething(18.3);

Tried your code, but even simple calls did not work out of box. Main problem is that MyClass contains unknown element type 'myEement' - that type cannot be deduced from function call parameters. However - if you make a generalization and omit object type - your sample will work in out of box manner:
using System;
using System.Collections.Generic;
interface ISomePolicy<U>
{
void _doSomething(U u);
}
public class MyClass<U> :
ISomePolicy<double>,
ISomePolicy<int>
{
internal object myEement { get; set; }
public MyClass(object Element)
{
myEement = Element;
}
void ISomePolicy<double>._doSomething(double u)
{
Console.WriteLine("this is double");
}
void ISomePolicy<int>._doSomething(int u)
{
Console.WriteLine("this is int");
}
}
static class MyClassExtension
{
public static void doSomething<P, U>(this P oTh, U u) where P : ISomePolicy<U>
{
oTh._doSomething(u);
}
}
class Program
{
static void Main()
{
MyClass<double> oClass = new MyClass<double>(3);
oClass.doSomething(0.5); //This works
oClass.doSomething(1); //This works
//oClass.doSomething("Will not work");
}
}
What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.
myElement.GetType(), or cast to it - e.g.
if( myElement is int ) DoSomethingWithInt( (int) myElement );
However - reflection always might slow down your execution. If you don't intend to create super heavy class hierarchy with huge amount of instances - then this should be sufficient for your needs.

Related

C# type safe union [duplicate]

[Note: This question had the original title "C (ish) style union in C#"
but as Jeff's comment informed me, apparently this structure is called a 'discriminated union']
Excuse the verbosity of this question.
There are a couple of similar sounding questions to mine already in SO but they seem to concentrate on the memory saving benefits of the union or using it for interop.
Here is an example of such a question.
My desire to have a union type thing is somewhat different.
I am writing some code at the moment which generates objects that look a bit like this
public class ValueWrapper
{
public DateTime ValueCreationDate;
// ... other meta data about the value
public object ValueA;
public object ValueB;
}
Pretty complicated stuff I think you will agree. The thing is that ValueA can only be of a few certain types (let's say string, int and Foo (which is a class) and ValueB can be another small set of types. I don't like treating these values as objects (I want the warm snugly feeling of coding with a bit of type safety).
So I thought about writing a trivial little wrapper class to express the fact that ValueA logically is a reference to a particular type. I called the class Union because what I am trying to achieve reminded me of the union concept in C.
public class Union<A, B, C>
{
private readonly Type type;
public readonly A a;
public readonly B b;
public readonly C c;
public A A{get {return a;}}
public B B{get {return b;}}
public C C{get {return c;}}
public Union(A a)
{
type = typeof(A);
this.a = a;
}
public Union(B b)
{
type = typeof(B);
this.b = b;
}
public Union(C c)
{
type = typeof(C);
this.c = c;
}
/// <summary>
/// Returns true if the union contains a value of type T
/// </summary>
/// <remarks>The type of T must exactly match the type</remarks>
public bool Is<T>()
{
return typeof(T) == type;
}
/// <summary>
/// Returns the union value cast to the given type.
/// </summary>
/// <remarks>If the type of T does not exactly match either X or Y, then the value <c>default(T)</c> is returned.</remarks>
public T As<T>()
{
if(Is<A>())
{
return (T)(object)a; // Is this boxing and unboxing unavoidable if I want the union to hold value types and reference types?
//return (T)x; // This will not compile: Error = "Cannot cast expression of type 'X' to 'T'."
}
if(Is<B>())
{
return (T)(object)b;
}
if(Is<C>())
{
return (T)(object)c;
}
return default(T);
}
}
Using this class ValueWrapper now looks like this
public class ValueWrapper2
{
public DateTime ValueCreationDate;
public Union<int, string, Foo> ValueA;
public Union<double, Bar, Foo> ValueB;
}
which is something like what I wanted to achieve but I am missing one fairly crucial element - that is compiler enforced type checking when calling the Is and As functions as the following code demonstrates
public void DoSomething()
{
if(ValueA.Is<string>())
{
var s = ValueA.As<string>();
// .... do somethng
}
if(ValueA.Is<char>()) // I would really like this to be a compile error
{
char c = ValueA.As<char>();
}
}
IMO It is not valid to ask ValueA if it is a char since its definition clearly says it is not - this is a programming error and I would like the compiler to pick up on this. [Also if I could get this correct then (hopefully) I would get intellisense too - which would be a boon.]
In order to achieve this I would want to tell the compiler that the type T can be one of A, B or C
public bool Is<T>() where T : A
or T : B // Yes I know this is not legal!
or T : C
{
return typeof(T) == type;
}
Does anyone have any idea if what I want to achieve is possible? Or am I just plain stupid for writing this class in the first place?
I don't really like the type-checking and type-casting solutions provided above, so here's 100% type-safe union which will throw compilation errors if you attempt to use the wrong datatype:
using System;
namespace Juliet
{
class Program
{
static void Main(string[] args)
{
Union3<int, char, string>[] unions = new Union3<int,char,string>[]
{
new Union3<int, char, string>.Case1(5),
new Union3<int, char, string>.Case2('x'),
new Union3<int, char, string>.Case3("Juliet")
};
foreach (Union3<int, char, string> union in unions)
{
string value = union.Match(
num => num.ToString(),
character => new string(new char[] { character }),
word => word);
Console.WriteLine("Matched union with value '{0}'", value);
}
Console.ReadLine();
}
}
public abstract class Union3<A, B, C>
{
public abstract T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h);
// private ctor ensures no external classes can inherit
private Union3() { }
public sealed class Case1 : Union3<A, B, C>
{
public readonly A Item;
public Case1(A item) : base() { this.Item = item; }
public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
{
return f(Item);
}
}
public sealed class Case2 : Union3<A, B, C>
{
public readonly B Item;
public Case2(B item) { this.Item = item; }
public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
{
return g(Item);
}
}
public sealed class Case3 : Union3<A, B, C>
{
public readonly C Item;
public Case3(C item) { this.Item = item; }
public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
{
return h(Item);
}
}
}
}
I like the direction of the accepted solution but it doesn't scale well for unions of more than three items (e.g. a union of 9 items would require 9 class definitions).
Here is another approach that is also 100% type-safe at compile-time, but that is easy to grow to large unions.
public class UnionBase<A>
{
dynamic value;
public UnionBase(A a) { value = a; }
protected UnionBase(object x) { value = x; }
protected T InternalMatch<T>(params Delegate[] ds)
{
var vt = value.GetType();
foreach (var d in ds)
{
var mi = d.Method;
// These are always true if InternalMatch is used correctly.
Debug.Assert(mi.GetParameters().Length == 1);
Debug.Assert(typeof(T).IsAssignableFrom(mi.ReturnType));
var pt = mi.GetParameters()[0].ParameterType;
if (pt.IsAssignableFrom(vt))
return (T)mi.Invoke(null, new object[] { value });
}
throw new Exception("No appropriate matching function was provided");
}
public T Match<T>(Func<A, T> fa) { return InternalMatch<T>(fa); }
}
public class Union<A, B> : UnionBase<A>
{
public Union(A a) : base(a) { }
public Union(B b) : base(b) { }
protected Union(object x) : base(x) { }
public T Match<T>(Func<A, T> fa, Func<B, T> fb) { return InternalMatch<T>(fa, fb); }
}
public class Union<A, B, C> : Union<A, B>
{
public Union(A a) : base(a) { }
public Union(B b) : base(b) { }
public Union(C c) : base(c) { }
protected Union(object x) : base(x) { }
public T Match<T>(Func<A, T> fa, Func<B, T> fb, Func<C, T> fc) { return InternalMatch<T>(fa, fb, fc); }
}
public class Union<A, B, C, D> : Union<A, B, C>
{
public Union(A a) : base(a) { }
public Union(B b) : base(b) { }
public Union(C c) : base(c) { }
public Union(D d) : base(d) { }
protected Union(object x) : base(x) { }
public T Match<T>(Func<A, T> fa, Func<B, T> fb, Func<C, T> fc, Func<D, T> fd) { return InternalMatch<T>(fa, fb, fc, fd); }
}
public class Union<A, B, C, D, E> : Union<A, B, C, D>
{
public Union(A a) : base(a) { }
public Union(B b) : base(b) { }
public Union(C c) : base(c) { }
public Union(D d) : base(d) { }
public Union(E e) : base(e) { }
protected Union(object x) : base(x) { }
public T Match<T>(Func<A, T> fa, Func<B, T> fb, Func<C, T> fc, Func<D, T> fd, Func<E, T> fe) { return InternalMatch<T>(fa, fb, fc, fd, fe); }
}
public class DiscriminatedUnionTest : IExample
{
public Union<int, bool, string, int[]> MakeUnion(int n)
{
return new Union<int, bool, string, int[]>(n);
}
public Union<int, bool, string, int[]> MakeUnion(bool b)
{
return new Union<int, bool, string, int[]>(b);
}
public Union<int, bool, string, int[]> MakeUnion(string s)
{
return new Union<int, bool, string, int[]>(s);
}
public Union<int, bool, string, int[]> MakeUnion(params int[] xs)
{
return new Union<int, bool, string, int[]>(xs);
}
public void Print(Union<int, bool, string, int[]> union)
{
var text = union.Match(
n => "This is an int " + n.ToString(),
b => "This is a boolean " + b.ToString(),
s => "This is a string" + s,
xs => "This is an array of ints " + String.Join(", ", xs));
Console.WriteLine(text);
}
public void Run()
{
Print(MakeUnion(1));
Print(MakeUnion(true));
Print(MakeUnion("forty-two"));
Print(MakeUnion(0, 1, 1, 2, 3, 5, 8));
}
}
I wrote some blog posts on this subject that might be useful:
Union Types in C#
Implementing Tic-Tac-Toe Using State Classes
Let's say you have a shopping cart scenario with three states: "Empty", "Active" and "Paid", each with different behavior.
You create have a ICartState interface that all states have in common (and it could just be an empty marker interface)
You create three classes that implement that interface. (The classes do not have to be in an inheritance relationship)
The interface contains a "fold" method, whereby you pass a lambda in for each state or case that you need to handle.
You could use the F# runtime from C# but as a lighter weight alternative, I have written a little T4 template for generating code like this.
Here's the interface:
partial interface ICartState
{
ICartState Transition(
Func<CartStateEmpty, ICartState> cartStateEmpty,
Func<CartStateActive, ICartState> cartStateActive,
Func<CartStatePaid, ICartState> cartStatePaid
);
}
And here's the implementation:
class CartStateEmpty : ICartState
{
ICartState ICartState.Transition(
Func<CartStateEmpty, ICartState> cartStateEmpty,
Func<CartStateActive, ICartState> cartStateActive,
Func<CartStatePaid, ICartState> cartStatePaid
)
{
// I'm the empty state, so invoke cartStateEmpty
return cartStateEmpty(this);
}
}
class CartStateActive : ICartState
{
ICartState ICartState.Transition(
Func<CartStateEmpty, ICartState> cartStateEmpty,
Func<CartStateActive, ICartState> cartStateActive,
Func<CartStatePaid, ICartState> cartStatePaid
)
{
// I'm the active state, so invoke cartStateActive
return cartStateActive(this);
}
}
class CartStatePaid : ICartState
{
ICartState ICartState.Transition(
Func<CartStateEmpty, ICartState> cartStateEmpty,
Func<CartStateActive, ICartState> cartStateActive,
Func<CartStatePaid, ICartState> cartStatePaid
)
{
// I'm the paid state, so invoke cartStatePaid
return cartStatePaid(this);
}
}
Now let's say you extend the CartStateEmpty and CartStateActive with an AddItem method which is not implemented by CartStatePaid.
And also let's say that CartStateActive has a Pay method that the other states dont have.
Then here's some code that shows it in use -- adding two items and then paying for the cart:
public ICartState AddProduct(ICartState currentState, Product product)
{
return currentState.Transition(
cartStateEmpty => cartStateEmpty.AddItem(product),
cartStateActive => cartStateActive.AddItem(product),
cartStatePaid => cartStatePaid // not allowed in this case
);
}
public void Example()
{
var currentState = new CartStateEmpty() as ICartState;
//add some products
currentState = AddProduct(currentState, Product.ProductX);
currentState = AddProduct(currentState, Product.ProductY);
//pay
const decimal paidAmount = 12.34m;
currentState = currentState.Transition(
cartStateEmpty => cartStateEmpty, // not allowed in this case
cartStateActive => cartStateActive.Pay(paidAmount),
cartStatePaid => cartStatePaid // not allowed in this case
);
}
Note that this code is completely typesafe -- no casting or conditionals anywhere, and compiler errors if you try to pay for an empty cart, say.
I have written a library for doing this at https://github.com/mcintyre321/OneOf
Install-Package OneOf
It has the generic types in it for doing DUs e.g. OneOf<T0, T1> all the way to
OneOf<T0, ..., T9>. Each of those has a .Match, and a .Switch statement which you can use for compiler safe typed behaviour, e.g.:
```
OneOf<string, ColorName, Color> backgroundColor = getBackground();
Color c = backgroundColor.Match(
str => CssHelper.GetColorFromString(str),
name => new Color(name),
col => col
);
```
I am not sure I fully understand your goal. In C, a union is a structure that uses the same memory locations for more than one field. For example:
typedef union
{
float real;
int scalar;
} floatOrScalar;
The floatOrScalar union could be used as a float, or an int, but they both consume the same memory space. Changing one changes the other. You can achieve the same thing with a struct in C#:
[StructLayout(LayoutKind.Explicit)]
struct FloatOrScalar
{
[FieldOffset(0)]
public float Real;
[FieldOffset(0)]
public int Scalar;
}
The above structure uses 32bits total, rather than 64bits. This is only possible with a struct. Your example above is a class, and given the nature of the CLR, makes no guarantee about memory efficiency. If you change a Union<A, B, C> from one type to another, you are not necessarily reusing memory...most likely, you are allocating a new type on the heap and dropping a different pointer in the backing object field. Contrary to a real union, your approach may actually cause more heap thrashing than you would otherwise get if you did not use your Union type.
char foo = 'B';
bool bar = foo is int;
This results in a warning, not an error. If you're looking for your Is and As functions to be analogs for the C# operators, then you shouldn't be restricting them in that way anyhow.
If you allow multiple types, you cannot achieve type safety (unless the types are related).
You can't and won't achieve any kind of type safety, you could only achieve byte-value-safety using FieldOffset.
It would make much more sense to have a generic ValueWrapper<T1, T2> with T1 ValueA and T2 ValueB, ...
P.S.: when talking about type-safety I mean compile-time type-safety.
If you need a code wrapper (performing bussiness logic on modifications you can use something along the lines of:
public class Wrapper
{
public ValueHolder<int> v1 = 5;
public ValueHolder<byte> v2 = 8;
}
public struct ValueHolder<T>
where T : struct
{
private T value;
public ValueHolder(T value) { this.value = value; }
public static implicit operator T(ValueHolder<T> valueHolder) { return valueHolder.value; }
public static implicit operator ValueHolder<T>(T value) { return new ValueHolder<T>(value); }
}
For an easy way out you could use (it has performance issues, but it is very simple):
public class Wrapper
{
private object v1;
private object v2;
public T GetValue1<T>() { if (v1.GetType() != typeof(T)) throw new InvalidCastException(); return (T)v1; }
public void SetValue1<T>(T value) { v1 = value; }
public T GetValue2<T>() { if (v2.GetType() != typeof(T)) throw new InvalidCastException(); return (T)v2; }
public void SetValue2<T>(T value) { v2 = value; }
}
//usage:
Wrapper wrapper = new Wrapper();
wrapper.SetValue1("aaaa");
wrapper.SetValue2(456);
string s = wrapper.GetValue1<string>();
DateTime dt = wrapper.GetValue1<DateTime>();//InvalidCastException
Here is my attempt. It does compile time checking of types, using generic type constraints.
class Union {
public interface AllowedType<T> { };
internal object val;
internal System.Type type;
}
static class UnionEx {
public static T As<U,T>(this U x) where U : Union, Union.AllowedType<T> {
return x.type == typeof(T) ?(T)x.val : default(T);
}
public static void Set<U,T>(this U x, T newval) where U : Union, Union.AllowedType<T> {
x.val = newval;
x.type = typeof(T);
}
public static bool Is<U,T>(this U x) where U : Union, Union.AllowedType<T> {
return x.type == typeof(T);
}
}
class MyType : Union, Union.AllowedType<int>, Union.AllowedType<string> {}
class TestIt
{
static void Main()
{
MyType bla = new MyType();
bla.Set(234);
System.Console.WriteLine(bla.As<MyType,int>());
System.Console.WriteLine(bla.Is<MyType,string>());
System.Console.WriteLine(bla.Is<MyType,int>());
bla.Set("test");
System.Console.WriteLine(bla.As<MyType,string>());
System.Console.WriteLine(bla.Is<MyType,string>());
System.Console.WriteLine(bla.Is<MyType,int>());
// compile time errors!
// bla.Set('a');
// bla.Is<MyType,char>()
}
}
It could use some prettying-up. Especially, I couldn't figure out how to get rid of the type parameters to As/Is/Set (isn't there a way to specify one type parameter and let C# figure the other one?)
So I've hit this same problem many times, and I just came up with a solution that gets the syntax I want (at the expense of some ugliness in the implementation of the Union type.)
To recap: we want this sort of usage at the call site.
Union<int, string> u;
u = 1492;
int yearColumbusDiscoveredAmerica = u;
u = "hello world";
string traditionalGreeting = u;
var answers = new SortedList<string, Union<int, string, DateTime>>();
answers["life, the universe, and everything"] = 42;
answers["D-Day"] = new DateTime(1944, 6, 6);
answers["C#"] = "is awesome";
We want the following examples to fail to compile, however, so that we get a modicum of type safety.
DateTime dateTimeColumbusDiscoveredAmerica = u;
Foo fooInstance = u;
For extra credit, let's also not take up more space than absolutely needed.
With all that said, here's my implementation for two generic type parameters. The implementation for three, four, and so on type parameters is straight-forward.
public abstract class Union<T1, T2>
{
public abstract int TypeSlot
{
get;
}
public virtual T1 AsT1()
{
throw new TypeAccessException(string.Format(
"Cannot treat this instance as a {0} instance.", typeof(T1).Name));
}
public virtual T2 AsT2()
{
throw new TypeAccessException(string.Format(
"Cannot treat this instance as a {0} instance.", typeof(T2).Name));
}
public static implicit operator Union<T1, T2>(T1 data)
{
return new FromT1(data);
}
public static implicit operator Union<T1, T2>(T2 data)
{
return new FromT2(data);
}
public static implicit operator Union<T1, T2>(Tuple<T1, T2> data)
{
return new FromTuple(data);
}
public static implicit operator T1(Union<T1, T2> source)
{
return source.AsT1();
}
public static implicit operator T2(Union<T1, T2> source)
{
return source.AsT2();
}
private class FromT1 : Union<T1, T2>
{
private readonly T1 data;
public FromT1(T1 data)
{
this.data = data;
}
public override int TypeSlot
{
get { return 1; }
}
public override T1 AsT1()
{
return this.data;
}
public override string ToString()
{
return this.data.ToString();
}
public override int GetHashCode()
{
return this.data.GetHashCode();
}
}
private class FromT2 : Union<T1, T2>
{
private readonly T2 data;
public FromT2(T2 data)
{
this.data = data;
}
public override int TypeSlot
{
get { return 2; }
}
public override T2 AsT2()
{
return this.data;
}
public override string ToString()
{
return this.data.ToString();
}
public override int GetHashCode()
{
return this.data.GetHashCode();
}
}
private class FromTuple : Union<T1, T2>
{
private readonly Tuple<T1, T2> data;
public FromTuple(Tuple<T1, T2> data)
{
this.data = data;
}
public override int TypeSlot
{
get { return 0; }
}
public override T1 AsT1()
{
return this.data.Item1;
}
public override T2 AsT2()
{
return this.data.Item2;
}
public override string ToString()
{
return this.data.ToString();
}
public override int GetHashCode()
{
return this.data.GetHashCode();
}
}
}
And my attempt on minimal yet extensible solution using nesting of Union/Either type.
Also usage of default parameters in Match method naturally enables "Either X Or Default" scenario.
using System;
using System.Reflection;
using NUnit.Framework;
namespace Playground
{
[TestFixture]
public class EitherTests
{
[Test]
public void Test_Either_of_Property_or_FieldInfo()
{
var some = new Some(false);
var field = some.GetType().GetField("X");
var property = some.GetType().GetProperty("Y");
Assert.NotNull(field);
Assert.NotNull(property);
var info = Either<PropertyInfo, FieldInfo>.Of(field);
var infoType = info.Match(p => p.PropertyType, f => f.FieldType);
Assert.That(infoType, Is.EqualTo(typeof(bool)));
}
[Test]
public void Either_of_three_cases_using_nesting()
{
var some = new Some(false);
var field = some.GetType().GetField("X");
var parameter = some.GetType().GetConstructors()[0].GetParameters()[0];
Assert.NotNull(field);
Assert.NotNull(parameter);
var info = Either<ParameterInfo, Either<PropertyInfo, FieldInfo>>.Of(parameter);
var name = info.Match(_ => _.Name, _ => _.Name, _ => _.Name);
Assert.That(name, Is.EqualTo("a"));
}
public class Some
{
public bool X;
public string Y { get; set; }
public Some(bool a)
{
X = a;
}
}
}
public static class Either
{
public static T Match<A, B, C, T>(
this Either<A, Either<B, C>> source,
Func<A, T> a = null, Func<B, T> b = null, Func<C, T> c = null)
{
return source.Match(a, bc => bc.Match(b, c));
}
}
public abstract class Either<A, B>
{
public static Either<A, B> Of(A a)
{
return new CaseA(a);
}
public static Either<A, B> Of(B b)
{
return new CaseB(b);
}
public abstract T Match<T>(Func<A, T> a = null, Func<B, T> b = null);
private sealed class CaseA : Either<A, B>
{
private readonly A _item;
public CaseA(A item) { _item = item; }
public override T Match<T>(Func<A, T> a = null, Func<B, T> b = null)
{
return a == null ? default(T) : a(_item);
}
}
private sealed class CaseB : Either<A, B>
{
private readonly B _item;
public CaseB(B item) { _item = item; }
public override T Match<T>(Func<A, T> a = null, Func<B, T> b = null)
{
return b == null ? default(T) : b(_item);
}
}
}
}
You could throw exceptions once there's an attempt to access variables that haven't been initialized, ie if it's created with an A parameter and later on there's an attempt to access B or C, it could throw, say, UnsupportedOperationException. You'd need a getter to make it work though.
The C# Language Design Team discussed discriminated unions in January 2017 https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-01-10.md#discriminated-unions-via-closed-types
You can vote for the feature request at https://github.com/dotnet/csharplang/issues/113
You can export a pseudo-pattern matching function, like I use for the Either type in my Sasa library. There's currently runtime overhead, but I eventually plan to add a CIL analysis to inline all the delegates into a true case statement.
It's not possible to do with exactly the syntax you've used but with a bit more verbosity and copy/paste it's easy to make overload resolution do the job for you:
// this code is ok
var u = new Union("");
if (u.Value(Is.OfType()))
{
u.Value(Get.ForType());
}
// and this one will not compile
if (u.Value(Is.OfType()))
{
u.Value(Get.ForType());
}
By now it should be pretty obvious how to implement it:
public class Union
{
private readonly Type type;
public readonly A a;
public readonly B b;
public readonly C c;
public Union(A a)
{
type = typeof(A);
this.a = a;
}
public Union(B b)
{
type = typeof(B);
this.b = b;
}
public Union(C c)
{
type = typeof(C);
this.c = c;
}
public bool Value(TypeTestSelector _)
{
return typeof(A) == type;
}
public bool Value(TypeTestSelector _)
{
return typeof(B) == type;
}
public bool Value(TypeTestSelector _)
{
return typeof(C) == type;
}
public A Value(GetValueTypeSelector _)
{
return a;
}
public B Value(GetValueTypeSelector _)
{
return b;
}
public C Value(GetValueTypeSelector _)
{
return c;
}
}
public static class Is
{
public static TypeTestSelector OfType()
{
return null;
}
}
public class TypeTestSelector
{
}
public static class Get
{
public static GetValueTypeSelector ForType()
{
return null;
}
}
public class GetValueTypeSelector
{
}
There are no checks for extracting the value of the wrong type, e.g.:
var u = Union(10);
string s = u.Value(Get.ForType());
So you might consider adding necessary checks and throw exceptions in such cases.
I am currently trying to create a Julia Runtime in .NET. Julia has types like Union{Int, String}... Etc. I am currently trying to simulate this .NET (without doing weird IL that would not be able to be called from c#).
Here is a compile time implementation of a union of structures. I will be creating more unions for object unions, and cross object and struct unions (this will be the most complex case).
public struct Union<T1,T2> where T1 : struct where T2 : struct{
private byte type;
[FieldOffset(1)] private T1 a1;
[FieldOffset(1)] private T2 a2;
public T1 A1 {
get => a1;
set {
a1 = value;
type = 1;
}
}
public T2 A2 {
get => a2;
set {
a2 = value;
type = 2;
}
}
public Union(int _ = 0) {
type = 0;
a1 = default;
a2 = default;
}
public Union(T1 a) : this() => A1 = a;
public Union(T2 a) : this() => A2 = a;
public bool HasValue => type < 1 || type > 2;
public bool IsNull => !HasValue;
public bool IsT1 => type == 1;
public bool IsT2 => type == 2;
public Type GetType() {
switch (type) {
case 1: return typeof(T1);
case 2: return typeof(T2);
default: return null;
}
}
}
You can use the above like the following:
Union<int, long> myUnion(5); \\Set int inside
myUnion.a2 = 5;
Type theTypeInside = myUnion.GetType(); //long
myUnion.a1 = 5;
theTypeInside = myUnion.GetType(); //int
I will also be creating dynamic union generators or aligned unions for the cross object and struct union.
Take a look at:Generated Struct Union Output to see the current compile time unions I am using.
If you want to create a union of any size take a look at Generator for Struct Unions
If anyone has any improvements for the above let me know! Implementing julia into .NET is an extraordinarily hard task!
I use own of Union Type.
Consider an example to make it clearer.
Imagine we have Contact class:
public class Contact
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public string PostalAdrress { get; set; }
}
These are all defined as simple strings, but really are they just strings?
Of course not. The Name can consist of First Name and Last Name. Or is an Email just a set of symbols? I know that at least it should contain # and it is necessarily.
Let's improve us domain model
public class PersonalName
{
public PersonalName(string firstName, string lastName) { ... }
public string Name() { return _fistName + " " _lastName; }
}
public class EmailAddress
{
public EmailAddress(string email) { ... }
}
public class PostalAdrress
{
public PostalAdrress(string address, string city, int zip) { ... }
}
In this classes will be validations during creating and we will eventually have valid models. Consturctor in PersonaName class require FirstName and LastName at the same time. This means that after the creation, it can not have invalid state.
And contact class respectively
public class Contact
{
public PersonalName Name { get; set; }
public EmailAdress EmailAddress { get; set; }
public PostalAddress PostalAddress { get; set; }
}
In this case we have same problem, object of Contact class may be in invalid state. I mean it may have EmailAddress but haven't Name
var contact = new Contact { EmailAddress = new EmailAddress("foo#bar.com") };
Let's fix it and create Contact class with constructor which requires PersonalName, EmailAddress and PostalAddress:
public class Contact
{
public Contact(
PersonalName personalName,
EmailAddress emailAddress,
PostalAddress postalAddress
)
{
...
}
}
But here we have another problem. What if Person have only EmailAdress and haven't PostalAddress?
If we think about it there we realize that there are three possibilities of valid state of Contact class object:
A contact only has an email address
A contact only has a postal address
A contact has both an email address and a postal address
Let's write out domain models. For the beginning we will create Contact Info class which state will be corresponding with above cases.
public class ContactInfo
{
public ContactInfo(EmailAddress emailAddress) { ... }
public ContactInfo(PostalAddress postalAddress) { ... }
public ContactInfo(Tuple<EmailAddress,PostalAddress> emailAndPostalAddress) { ... }
}
And Contact class:
public class Contact
{
public Contact(
PersonalName personalName,
ContactInfo contactInfo
)
{
...
}
}
Let's try use it:
var contact = new Contact(
new PersonalName("James", "Bond"),
new ContactInfo(
new EmailAddress("agent#007.com")
)
);
Console.WriteLine(contact.PersonalName()); // James Bond
Console.WriteLine(contact.ContactInfo().???) // here we have problem, because ContactInfo have three possible state and if we want print it we would write `if` cases
Let's add Match method in ContactInfo class
public class ContactInfo
{
// constructor
public TResult Match<TResult>(
Func<EmailAddress,TResult> f1,
Func<PostalAddress,TResult> f2,
Func<Tuple<EmailAddress,PostalAddress>> f3
)
{
if (_emailAddress != null)
{
return f1(_emailAddress);
}
else if(_postalAddress != null)
{
...
}
...
}
}
In the match method, we can write this code, because the state of the contact class is controlled with constructors and it may have only one of the possible states.
Let's create an auxiliary class, so that each time do not write as many code.
public abstract class Union<T1,T2,T3>
where T1 : class
where T2 : class
where T3 : class
{
private readonly T1 _t1;
private readonly T2 _t2;
private readonly T3 _t3;
public Union(T1 t1) { _t1 = t1; }
public Union(T2 t2) { _t2 = t2; }
public Union(T3 t3) { _t3 = t3; }
public TResult Match<TResult>(
Func<T1, TResult> f1,
Func<T2, TResult> f2,
Func<T3, TResult> f3
)
{
if (_t1 != null)
{
return f1(_t1);
}
else if (_t2 != null)
{
return f2(_t2);
}
else if (_t3 != null)
{
return f3(_t3);
}
throw new Exception("can't match");
}
}
We can have such a class in advance for several types, as is done with delegates Func, Action. 4-6 generic type parameters will be in full for Union class.
Let's rewrite ContactInfo class:
public sealed class ContactInfo : Union<
EmailAddress,
PostalAddress,
Tuple<EmaiAddress,PostalAddress>
>
{
public Contact(EmailAddress emailAddress) : base(emailAddress) { }
public Contact(PostalAddress postalAddress) : base(postalAddress) { }
public Contact(Tuple<EmaiAddress, PostalAddress> emailAndPostalAddress) : base(emailAndPostalAddress) { }
}
Here the compiler will ask override for at least one constructor. If we forget to override the rest of the constructors we can't create object of ContactInfo class with another state. This will protect us from runtime exceptions during Matching.
var contact = new Contact(
new PersonalName("James", "Bond"),
new ContactInfo(
new EmailAddress("agent#007.com")
)
);
Console.WriteLine(contact.PersonalName()); // James Bond
Console
.WriteLine(
contact
.ContactInfo()
.Match(
(emailAddress) => emailAddress.Address,
(postalAddress) => postalAddress.City + " " postalAddress.Zip.ToString(),
(emailAndPostalAddress) => emailAndPostalAddress.Item1.Name + emailAndPostalAddress.Item2.City + " " emailAndPostalAddress.Item2.Zip.ToString()
)
);
That's all.
I hope you enjoyed.
Example taken from the site F# for fun and profit

C# generic operators - RTTI approach

I intend to ask about generic operator+ overloading but not in typical "can I do operator+ for generic type" way.
Questions are on the bottom
I recently started to create matrix class in C# and after a while It came to me that I cannot do simple T + T !
Thus, I googled and googled and found several workarounds.
Create Expression link
Create abstract class abstract class Matrix<T>{//some code}. Create 'protected virtual method Add(T itemToAdd)' and then create
operator like this : T operator+(T item1, T item2){return item1.Add(item2);}(most posts on stack) and then inherit this method in class Matrix : Matrix<int> here
Use method Add such as : T Add(T first, T second){ dynamic output = first + second; return output;} (somewhere on stack)
First one just does not suited me so I tried second one but then I run onto serious problems like:
(A LOT of )repetative code - I created 4 classes for : int, double, long, Complex - my own type
Creating multiple extension methods and so on.
Third one is just so unsafe that I rejected it immidietlay.
After my struggling I came to realise : 'Why don't I use RTTI and reflection?' I know, it is expensive in running time but why not use static constructor to do this?
Here is my idea (pseudocode):
class Matrix<T>{
static Func<T,T,T> Add;
static Matrix
{
if(T is int)
Add = (first,second) = > ((int)first)+((int)second);
else if(T is long)
Add = (first,second) = > ((long)first)+((long)second);
// and so on for built-in types
else
{ // T is not built-in type
if(typeof(T).GetMethods().Contains("op_Addition"))
{
Add = (first,second) => typeof(T).getMethod("op_Addition").invoke(first,second);
}
}
}
I know that reflection is costly but it will do it only one time (per type)!
And before you start argue : I am going to code T is int like this :
var type = typeof(T);
if(type==typeof(int)) // code
I am aware that I cannot explicitly convert T to int but there must be some sort of 'work around'. Problem is that (for example) Int32 has not explicit 'method' for operator+ hence, reflection is not of much use.
After all that introduction I have two questions :
Is it a good approach or do you see major flaws in it?
Is it doable? I don't want to start creating code without knowing for sure that my lambda function WILL work.
EDIT 1+2
I changed my code to generic.
I figured that maybe you need an usage of my class, here you are :
Matrix<int> matrix = new Matrix(1,1); // creates int-based matrix
Matrix<MyClass> matrix2 = new Matrix(1,1); // creates some other type matrix
ANSWER
based on dasblinkenlight's answer I managed to do this :
public interface ITypeTratis<T>
{
T Add(T a, T b);
T Mul(T a, T b);
T Sub(T a, T b);
T Div(T a, T b);
bool Eq(T a, T b);
}
public class IntTypeTratis : ITypeTratis<int>
{
//code for int
}
public class DoubleTypeTratis : ITypeTratis<double>
{
//code for double
}
internal class TypeTraits<T> : ITypeTratis<T>
{
public Func<T, T, T> AddF;
public Func<T, T, T> MulF;
public Func<T, T, T> DivF;
public Func<T, T, T> SubF;
public Func<T, T, bool> EqF;
public T Add(T a, T b) => AddF(a, b);
public bool Eq(T a, T b) => EqF(a, b);
public T Mul(T a, T b) => MulF(a, b);
public T Sub(T a, T b) => SubF(a, b);
public T Div(T a, T b) => DivF(a, b);
}
public class Matrix<T>
{
private static IDictionary<Type, object> traitByType = new Dictionary<Type, object>()
{
{typeof (int), new IntTypeTratis()},
{typeof (double), new DoubleTypeTratis()}
};
static Matrix()
{
Debug.WriteLine("Robie konstruktor dla " + typeof(T));
var type = typeof(T);
if (!traitByType.ContainsKey(type))
{
MethodInfo add, sub, mul, div, eq;
if ((add = type.GetMethod("op_Addition")) == null)
throw new NotSupportedException("Addition is not implemented");
if ((sub = type.GetMethod("op_Subtraction")) == null)
throw new NotSupportedException("Substraction is not implemented");
if ((mul = type.GetMethod("op_Multiply")) == null)
throw new NotSupportedException("Multiply is not implemented");
if ((div = type.GetMethod("op_Division")) == null)
throw new NotSupportedException("Division is not implemented");
if ((eq = type.GetMethod("op_Equality")) == null)
throw new NotSupportedException("Equality is not implemented");
var obj = new TypeTraits<T>
{
AddF = (a, b) => (T)add.Invoke(null, new object[] { a, b }),
SubF = (a, b) => (T)sub.Invoke(null, new object[] { a, b }),
MulF = (a, b) => (T)mul.Invoke(null, new object[] { a, b }),
DivF = (a, b) => (T)div.Invoke(null, new object[] { a, b }),
EqF = (a, b) => (bool)eq.Invoke(null, new object[] { a, b })
};
traitByType[type] = obj;
}
}
}
And this is exactly what I was looking for.
Yes, your approach will work fine.
Your static constructor will run for each type parameter T, ensuring that Add is set correctly.
You may want to separate out the addition logic into a separate class outside your matrix, and use that class to run operations based on type for your matrix. For example, if you also need multiplication, you could build a ITypeTraits<T> interface that has Add and Multiply:
public interface ITypeTraits<T> {
T Add(T a, T b);
T Mul(T a, T b);
}
Now you can build implementations of ITypeTraits<T> for individual types, e.g.
public class IntTypeTraits : ITypeTraits<int> {
public int Add(int a, int b) { return a+b; }
public int Mul(int a, int b) { return a*b; }
}
public class LongTypeTraits : ITypeTraits<long> {
public long Add(long a, long b) { return a+b; }
public long Mul(long a, long b) { return a*b; }
}
... // and so on
make a dictionary out of them
static readonly IDictionary<Type,object> traitByType = new Dictionary<Type,object> {
{typeof(int), new IntTypeTraits() }
, {typeof(long), new LongTypeTraits() }
... // and so on
};
and get the one you need to perform operations:
ITypeTraits<T> traits = (ITypeTraits<T>)traitByType(typeof(T));
T first = ...
T second = ...
T sum = traits.Add(first, second);
T prod = traits.Mul(first, second);
We can do this natively in C# 11 / .NET 7 (or above):
class Matrix<T> where T : INumber<T> // or just IAdditionOperators<T,T,T>
{
T x, y, z; // just to show we can do things
public T Sum() => x + y + z;
}
What is wrong with #3? You can just check for type, like so:
public abstract class Matrix<T>
{
public static HashSet<Type> AllowAdd = new HashSet<Type>
{
typeof(int),
typeof(long),
typeof(string),
typeof(double),
};
public T Add<T>(T first, T second)
{
if(!AllowAdd.Contains(typeof(T)))
{
throw new Exception(string.Format("Cannot preform addition for type: {0}", typeof(T).Name));
}
dynamic result = (dynamic)first + (dynamic)second;
return (T)result;
}
}
Bulding on dasblinkenlight's answer, here's my version of it. The benefit is that it doesn't need a dictionary lookup, instead making the type system do it. Should be faster, I think, but I haven't measured it. Also a bit less typing.
public abstract class MatrixBase
{
protected static class OperationDict<T>
{
private static Func<T,T,T> _notSupported = (a, b) => { throw new NotSupportedException(string.Format("Type {0} not supported for Matrix operations!", typeof(T))); };
public static Func<T, T, T> Add = _notSupported;
public static Func<T, T, T> Multiply = _notSupported;
}
static MatrixBase()
{
OperationDict<int>.Add = (a, b) => a + b;
OperationDict<int>.Multiply = (a, b) => a * b;
OperationDict<decimal>.Add = (a, b) => a + b;
OperationDict<decimal>.Multiply = (a, b) => a * b;
// Etc. for all supported types
}
}
public class Matrix<T> : MatrixBase
{
public T DoAdd(T a, T b)
{
return OperationDict<T>.Add(a, b);
}
}
I think you are on the right path, in order to avoid using reflection, you are required to somehow inform the compiler that you know "T" has the "+" operator, however, this feature does not yet exist in C#, so this is impossible to implement without runtime type checking or imposing other constraints.
If you don't care about the performance, you could use dynamic:
(dynamic)first + (dynamic)second
but that will take several reflection performance hits in every operation
Or you could use some other more complex approach that caches the specific methods in a dictionary, but you won't escape calling at least .GetType() in your add's implementation

Double dispatch in C# 4.0 - dynamic keyword?

I realise this has been asked before, but I didn't find a clear agreement on the best solution.
Is using dynamic (like below) the best way to do this?
I guess its best to avoid dynamic whenever possible to help catch problems at compile-time.
(classA1 and classA2 implement Interface A and likewise for B)
public static void Foo(InterfaceA a, InterfaceB b)
{
Foo((dynamic)a, (dynamic)b);
}
static void Foo(classA1 a, classB1 b) { //some code }
static void Foo(classA2 a, classB2 b) { //some code }
static void Foo(classA1 a, classB2 b) { //some code }
static void Foo(classA2 a, classB1 b) { //some code }
Or similarly...
public static void Foo(InterfaceA a, InterfaceB b)
{
((dynamic) a).Foo(b);
}
public classA1
{
void Foo(classB1 b) { //some code }
}
//repeated for other cases
Is using dynamic (like below) the best way to do this?
Well it's a way to do it - so long as the execution-time types will always end up with something that overload resolution will be happy with.
You might want to put a backstop method of
static void Foo(object x, object y)
in case none of the methods are applicable (e.g. a is a non-ClassA1/ClassA2 implementation). It's not going to help you if both values are null, mind you...
I would usually attempt to redesign so that this isn't required, but it's hard to know the best solution without more context.
Are 'classA1' and so on implementations of InterfaceA? If so then why not just declare the Foo functions as accepting InterfaceA and InterfaceB and cast them within to the concrete implementation expected by the function? E.g.,
static void Foo(InterfaceA a, InterfaceB b) {
classA1 c1 = a as classA1;
classB1 b1 = b as classB1;
// ... etc
}
Dynamic isn't intended to be used this way.
You could do something AWFUL with reflection - but I'm sure it's not better than doing dynamic:
void Main()
{
var a = "hello";//5;
var b = "hello";
var type1 = a.GetType();
var type2 = b.GetType();
var t = typeof(FooClass);
var methods = t.GetMethods();
foreach(var method in methods)
{
var parameters = method.GetParameters();
if(parameters.Length == 2)
{
if(parameters[0].ParameterType == type1
&& parameters[1].ParameterType == type2)
{
method.Invoke(this, new object[]{ a, b });
}
}
}
}
public static class FooClass
{
public static void Foo(int i, string s)
{
"Foo1".Dump();
}
public static void Foo(string s, string s2)
{
"Foo2".Dump();
}
}
C# has traditionally been a statically-typed language. The dynamic keyword adds dynamic typing to the language. The usual advice is to use "dynamic" sparingly. Here may be a case where you need it.
Generics won't cut it as this won't compile:
private void button1_Click(object sender, EventArgs e)
{
Foo(new classA1(), new classB2());
}
static void Foo<T, T1>(T a, T1 b) where T: InterfaceA
where T1: InterfaceB
{
Foo2(a, b);
}
static void Foo2(classA1 a, classB1 b) { }
static void Foo2(classA2 a, classB2 b) { }
static void Foo2(classA1 a, classB2 b) { }
static void Foo2(classA2 a, classB1 b) { }
interface InterfaceA { }
interface InterfaceB { }
class classA1 : InterfaceA { }
class classA2 : InterfaceA { }
class classB1 : InterfaceB { }
class classB2 : InterfaceB { }

Using LINQ query syntax with custom Maybe monad implementation

I am trying to write a simple Maybe monad in C#. I want to be able to use the LINQ query syntax with it. This is what I have come up with so far:
using System;
using System.Collections.Generic;
abstract class Maybe<A> {
public abstract Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f);
public abstract Maybe<B> Select<B>(Func<A, B> f);
}
class Just<A> : Maybe<A> {
private readonly A a;
public Just(A a) {
this.a = a;
}
override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
return f(a);
}
override public Maybe<B> Select<B>(Func<A, B> f) {
return new Just<B>(f(a));
}
override public string ToString() {
return "Just " + a;
}
}
class Nothing<A> : Maybe<A> {
override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
return new Nothing<B>();
}
override public Maybe<B> Select<B>(Func<A, B> f) {
return new Nothing<B>();
}
override public string ToString() {
return "Nothing";
}
}
static class Program {
public static void Main(string[] args) {
Maybe<int> m = new Just<int>(12);
Maybe<int> n = new Nothing<int>();
Maybe<int> result = from m0 in m
from n0 in n
select m0 + n0;
Console.WriteLine(result);
}
}
And this is the error message:
prog.cs(48,25): error CS1501: No overload for method `SelectMany' takes `2' arguments
prog.cs(5,28): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
Can anyone please guide me on what I should do to be able to use query syntax with my Maybe implementation? Thanks.
SelectMany must should be declared as an extension in a static class, for example:
public static class Maybe {
public static Maybe<B> SelectMany<B>(this Maybe<A> maybe, Func<A, Maybe<B>> f) {
return f(a);
}
...
}
EDIT:
you still need a piece. With this should work:
public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> m, Func<T, Maybe<U>> k, Func<T, U, V> s)
{
return m.SelectMany(x => k(x).SelectMany(y => new Just<V>(s(x, y))));
}
You need this because:
from m0 in m
from n0 in n
select m0 + n0
would be translated in:
m.SelectMany(m0 => n, (m, n0) => m0 + n0);
Instead, for example:
var aa = new List<List<string>>();
var bb = from a in aa
from b in a
select b;
is translated in
aa.SelectMany(a => a);

Simulate variadic templates in C#

Is there a well-known way for simulating the variadic template feature in C#?
For instance, I'd like to write a method that takes a lambda with an arbitrary set of parameters. Here is in pseudo code what I'd like to have:
void MyMethod<T1,T2,...,TReturn>(Fun<T1,T2, ..., TReturn> f)
{
}
C# generics are not the same as C++ templates. C++ templates are expanded compiletime and can be used recursively with variadic template arguments. The C++ template expansion is actually Turing Complete, so there is no theoretically limit to what can be done in templates.
C# generics are compiled directly, with an empty "placeholder" for the type that will be used at runtime.
To accept a lambda taking any number of arguments you would either have to generate a lot of overloads (through a code generator) or accept a LambdaExpression.
There is no varadic support for generic type arguments (on either methods or types). You will have to add lots of overloads.
varadic support is only available for arrays, via params, i.e.
void Foo(string key, params int[] values) {...}
Improtantly - how would you even refer to those various T* to write a generic method? Perhaps your best option is to take a Type[] or similar (depending on the context).
I know this is an old question, but if all you want to do is something simple like print those types out, you can do this very easily without Tuple or anything extra using 'dynamic':
private static void PrintTypes(params dynamic[] args)
{
foreach (var arg in args)
{
Console.WriteLine(arg.GetType());
}
}
static void Main(string[] args)
{
PrintTypes(1,1.0,"hello");
Console.ReadKey();
}
Will print "System.Int32" , "System.Double", "System.String"
If you want to perform some action on these things, as far as I know you have two choices. One is to trust the programmer that these types can do a compatible action, for example if you wanted to make a method to Sum any number of parameters. You could write a method like the following saying how you want to receive the result and the only prerequisite I guess would be that the + operation works between these types:
private static void AddToFirst<T>(ref T first, params dynamic[] args)
{
foreach (var arg in args)
{
first += arg;
}
}
static void Main(string[] args)
{
int x = 0;
AddToFirst(ref x,1,1.5,2.0,3.5,2);
Console.WriteLine(x);
double y = 0;
AddToFirst(ref y, 1, 1.5, 2.0, 3.5, 2);
Console.WriteLine(y);
Console.ReadKey();
}
With this, the output for the first line would be "9" because adding to an int, and the second line would be "10" because the .5s didn't get rounded, adding as a double. The problem with this code is if you pass some incompatible type in the list, it will have an error because the types can't get added together, and you won't see that error at compile time, only at runtime.
So, depending on your use case there might be another option which is why I said there were two choices at first. Assuming you know the choices for the possible types, you could make an interface or abstract class and make all of those types implement the interface. For example, the following. Sorry this is a bit crazy. And it can probably be simplfied.
public interface Applyable<T>
{
void Apply(T input);
T GetValue();
}
public abstract class Convertable<T>
{
public dynamic value { get; set; }
public Convertable(dynamic value)
{
this.value = value;
}
public abstract T GetConvertedValue();
}
public class IntableInt : Convertable<int>, Applyable<int>
{
public IntableInt(int value) : base(value) {}
public override int GetConvertedValue()
{
return value;
}
public void Apply(int input)
{
value += input;
}
public int GetValue()
{
return value;
}
}
public class IntableDouble : Convertable<int>
{
public IntableDouble(double value) : base(value) {}
public override int GetConvertedValue()
{
return (int) value;
}
}
public class IntableString : Convertable<int>
{
public IntableString(string value) : base(value) {}
public override int GetConvertedValue()
{
// If it can't be parsed return zero
int result;
return int.TryParse(value, out result) ? result : 0;
}
}
private static void ApplyToFirst<TResult>(ref Applyable<TResult> first, params Convertable<TResult>[] args)
{
foreach (var arg in args)
{
first.Apply(arg.GetConvertedValue());
}
}
static void Main(string[] args)
{
Applyable<int> result = new IntableInt(0);
IntableInt myInt = new IntableInt(1);
IntableDouble myDouble1 = new IntableDouble(1.5);
IntableDouble myDouble2 = new IntableDouble(2.0);
IntableDouble myDouble3 = new IntableDouble(3.5);
IntableString myString = new IntableString("2");
ApplyToFirst(ref result, myInt, myDouble1, myDouble2, myDouble3, myString);
Console.WriteLine(result.GetValue());
Console.ReadKey();
}
Will output "9" the same as the original Int code, except the only values you can actually pass in as parameters are things that you actually have defined and you know will work and not cause any errors. Of course, you would have to make new classes i.e. DoubleableInt , DoubleableString, etc.. in order to re-create the 2nd result of 10. But this is just an example, so you wouldn't even be trying to add things at all depending on what code you are writing and you would just start out with the implementation that served you the best.
Hopefully someone can improve on what I wrote here or use it to see how this can be done in C#.
Another alternative besides those mentioned above is to use Tuple<,> and reflection, for example:
class PrintVariadic<T>
{
public T Value { get; set; }
public void Print()
{
InnerPrint(Value);
}
static void InnerPrint<Tn>(Tn t)
{
var type = t.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Tuple<,>))
{
var i1 = type.GetProperty("Item1").GetValue(t, new object[]{});
var i2 = type.GetProperty("Item2").GetValue(t, new object[]{ });
InnerPrint(i1);
InnerPrint(i2);
return;
}
Console.WriteLine(t.GetType());
}
}
class Program
{
static void Main(string[] args)
{
var v = new PrintVariadic<Tuple<
int, Tuple<
string, Tuple<
double,
long>>>>();
v.Value = Tuple.Create(
1, Tuple.Create(
"s", Tuple.Create(
4.0,
4L)));
v.Print();
Console.ReadKey();
}
}
I don't necessarily know if there's a name for this pattern, but I arrived at the following formulation for a recursive generic interface that allows an unlimited amount of values to be passed in, with the returned type retaining type information for all passed values.
public interface ITraversalRoot<TRoot>
{
ITraversalSpecification<TRoot> Specify();
}
public interface ITraverser<TRoot, TCurrent>: ITraversalRoot<TRoot>
{
IDerivedTraverser<TRoot, TInclude, TCurrent, ITraverser<TRoot, TCurrent>> AndInclude<TInclude>(Expression<Func<TCurrent, TInclude>> path);
}
public interface IDerivedTraverser<TRoot, TDerived, TParent, out TParentTraverser> : ITraverser<TRoot, TParent>
{
IDerivedTraverser<TRoot, TInclude, TDerived, IDerivedTraverser<TRoot, TDerived, TParent, TParentTraverser>> FromWhichInclude<TInclude>(Expression<Func<TDerived, TInclude>> path);
TParentTraverser ThenBackToParent();
}
There's no casting or "cheating" of the type system involved here: you can keep stacking on more values and the inferred return type keeps storing more and more information. Here is what the usage looks like:
var spec = Traversal
.StartFrom<VirtualMachine>() // ITraverser<VirtualMachine, VirtualMachine>
.AndInclude(vm => vm.EnvironmentBrowser) // IDerivedTraverser<VirtualMachine, EnvironmentBrowser, VirtualMachine, ITraverser<VirtualMachine, VirtualMachine>>
.AndInclude(vm => vm.Datastore) // IDerivedTraverser<VirtualMachine, Datastore, VirtualMachine, ITraverser<VirtualMachine, VirtualMachine>>
.FromWhichInclude(ds => ds.Browser) // IDerivedTraverser<VirtualMachine, HostDatastoreBrowser, Datastore, IDerivedTraverser<VirtualMachine, Datastore, VirtualMachine, ITraverser<VirtualMachine, VirtualMachine>>>
.FromWhichInclude(br => br.Mountpoints) // IDerivedTraverser<VirtualMachine, Mountpoint, HostDatastoreBrowser, IDerivedTraverser<VirtualMachine, HostDatastoreBrowser, Datastore, IDerivedTraverser<VirtualMachine, Datastore, VirtualMachine, ITraverser<VirtualMachine, VirtualMachine>>>>
.Specify(); // ITraversalSpecification<VirtualMachine>
As you can see the type signature becomes basically unreadable near after a few chained calls, but this is fine so long as type inference works and suggests the right type to the user.
In my example I am dealing with Funcs arguments, but you could presumably adapt this code to deal with arguments of arbitrary type.
For a simulation you can say:
void MyMethod<TSource, TResult>(Func<TSource, TResult> f) where TSource : Tparams {
where Tparams to be a variadic arguments implementation class. However, the framework does not provide an out-of-box stuff to do that, Action, Func, Tuple, etc., are all have limited length of their signatures. The only thing I can think of is to apply the CRTP .. in a way I've not find somebody blogged. Here's my implementation:
*: Thank #SLaks for mentioning Tuple<T1, ..., T7, TRest> also works in a recursive way. I noticed it's recursive on the constructor and the factory method instead of its class definition; and do a runtime type checking of the last argument of type TRest is required to be a ITupleInternal; and this works a bit differently.
Code
using System;
namespace VariadicGenerics {
public interface INode {
INode Next {
get;
}
}
public interface INode<R>:INode {
R Value {
get; set;
}
}
public abstract class Tparams {
public static C<TValue> V<TValue>(TValue x) {
return new T<TValue>(x);
}
}
public class T<P>:C<P> {
public T(P x) : base(x) {
}
}
public abstract class C<R>:Tparams, INode<R> {
public class T<P>:C<T<P>>, INode<P> {
public T(C<R> node, P x) {
if(node is R) {
Next=(R)(node as object);
}
else {
Next=(node as INode<R>).Value;
}
Value=x;
}
public T() {
if(Extensions.TypeIs(typeof(R), typeof(C<>.T<>))) {
Next=(R)Activator.CreateInstance(typeof(R));
}
}
public R Next {
private set;
get;
}
public P Value {
get; set;
}
INode INode.Next {
get {
return this.Next as INode;
}
}
}
public new T<TValue> V<TValue>(TValue x) {
return new T<TValue>(this, x);
}
public int GetLength() {
return m_expandedArguments.Length;
}
public C(R x) {
(this as INode<R>).Value=x;
}
C() {
}
static C() {
m_expandedArguments=Extensions.GetExpandedGenericArguments(typeof(R));
}
// demonstration of non-recursive traversal
public INode this[int index] {
get {
var count = m_expandedArguments.Length;
for(INode node = this; null!=node; node=node.Next) {
if(--count==index) {
return node;
}
}
throw new ArgumentOutOfRangeException("index");
}
}
R INode<R>.Value {
get; set;
}
INode INode.Next {
get {
return null;
}
}
static readonly Type[] m_expandedArguments;
}
}
Note the type parameter for the inherited class C<> in the declaration of
public class T<P>:C<T<P>>, INode<P> {
is T<P>, and the class T<P> is nested so that you can do some crazy things such as:
Test
[Microsoft.VisualStudio.TestTools.UnitTesting.TestClass]
public class TestClass {
void MyMethod<TSource, TResult>(Func<TSource, TResult> f) where TSource : Tparams {
T<byte>.T<char>.T<uint>.T<long>.
T<byte>.T<char>.T<long>.T<uint>.
T<byte>.T<long>.T<char>.T<uint>.
T<long>.T<byte>.T<char>.T<uint>.
T<long>.T<byte>.T<uint>.T<char>.
T<byte>.T<long>.T<uint>.T<char>.
T<byte>.T<uint>.T<long>.T<char>.
T<byte>.T<uint>.T<char>.T<long>.
T<uint>.T<byte>.T<char>.T<long>.
T<uint>.T<byte>.T<long>.T<char>.
T<uint>.T<long>.T<byte>.T<char>.
T<long>.T<uint>.T<byte>.T<char>.
T<long>.T<uint>.T<char>.T<byte>.
T<uint>.T<long>.T<char>.T<byte>.
T<uint>.T<char>.T<long>.T<byte>.
T<uint>.T<char>.T<byte>.T<long>.
T<char>.T<uint>.T<byte>.T<long>.
T<char>.T<uint>.T<long>.T<byte>.
T<char>.T<long>.T<uint>.T<byte>.
T<long>.T<char>.T<uint>.T<byte>.
T<long>.T<char>.T<byte>.T<uint>.
T<char>.T<long>.T<byte>.T<uint>.
T<char>.T<byte>.T<long>.T<uint>.
T<char>.T<byte>.T<uint>.T<long>
crazy = Tparams
// trying to change any value to not match the
// declaring type makes the compilation fail
.V((byte)1).V('2').V(4u).V(8L)
.V((byte)1).V('2').V(8L).V(4u)
.V((byte)1).V(8L).V('2').V(4u)
.V(8L).V((byte)1).V('2').V(4u)
.V(8L).V((byte)1).V(4u).V('2')
.V((byte)1).V(8L).V(4u).V('2')
.V((byte)1).V(4u).V(8L).V('2')
.V((byte)1).V(4u).V('2').V(8L)
.V(4u).V((byte)1).V('2').V(8L)
.V(4u).V((byte)1).V(8L).V('2')
.V(4u).V(8L).V((byte)1).V('2')
.V(8L).V(4u).V((byte)1).V('2')
.V(8L).V(4u).V('9').V((byte)1)
.V(4u).V(8L).V('2').V((byte)1)
.V(4u).V('2').V(8L).V((byte)1)
.V(4u).V('2').V((byte)1).V(8L)
.V('2').V(4u).V((byte)1).V(8L)
.V('2').V(4u).V(8L).V((byte)1)
.V('2').V(8L).V(4u).V((byte)1)
.V(8L).V('2').V(4u).V((byte)1)
.V(8L).V('2').V((byte)1).V(4u)
.V('2').V(8L).V((byte)1).V(4u)
.V('2').V((byte)1).V(8L).V(4u)
.V('7').V((byte)1).V(4u).V(8L);
var args = crazy as TSource;
if(null!=args) {
f(args);
}
}
[TestMethod]
public void TestMethod() {
Func<
T<byte>.T<char>.T<uint>.T<long>.
T<byte>.T<char>.T<long>.T<uint>.
T<byte>.T<long>.T<char>.T<uint>.
T<long>.T<byte>.T<char>.T<uint>.
T<long>.T<byte>.T<uint>.T<char>.
T<byte>.T<long>.T<uint>.T<char>.
T<byte>.T<uint>.T<long>.T<char>.
T<byte>.T<uint>.T<char>.T<long>.
T<uint>.T<byte>.T<char>.T<long>.
T<uint>.T<byte>.T<long>.T<char>.
T<uint>.T<long>.T<byte>.T<char>.
T<long>.T<uint>.T<byte>.T<char>.
T<long>.T<uint>.T<char>.T<byte>.
T<uint>.T<long>.T<char>.T<byte>.
T<uint>.T<char>.T<long>.T<byte>.
T<uint>.T<char>.T<byte>.T<long>.
T<char>.T<uint>.T<byte>.T<long>.
T<char>.T<uint>.T<long>.T<byte>.
T<char>.T<long>.T<uint>.T<byte>.
T<long>.T<char>.T<uint>.T<byte>.
T<long>.T<char>.T<byte>.T<uint>.
T<char>.T<long>.T<byte>.T<uint>.
T<char>.T<byte>.T<long>.T<uint>.
T<char>.T<byte>.T<uint>.T<long>, String>
f = args => {
Debug.WriteLine(String.Format("Length={0}", args.GetLength()));
// print fourth value from the last
Debug.WriteLine(String.Format("value={0}", args.Next.Next.Next.Value));
args.Next.Next.Next.Value='x';
Debug.WriteLine(String.Format("value={0}", args.Next.Next.Next.Value));
return "test";
};
MyMethod(f);
}
}
Another thing to note is we have two classes named T, the non-nested T:
public class T<P>:C<P> {
is just for the consistency of usage, and I made class C abstract to not directly being newed.
The Code part above needs to expand ther generic argument to calculate about their length, here are two extension methods it used:
Code(extensions)
using System.Diagnostics;
using System;
namespace VariadicGenerics {
[DebuggerStepThrough]
public static class Extensions {
public static readonly Type VariadicType = typeof(C<>.T<>);
public static bool TypeIs(this Type x, Type d) {
if(null==d) {
return false;
}
for(var c = x; null!=c; c=c.BaseType) {
var a = c.GetInterfaces();
for(var i = a.Length; i-->=0;) {
var t = i<0 ? c : a[i];
if(t==d||t.IsGenericType&&t.GetGenericTypeDefinition()==d) {
return true;
}
}
}
return false;
}
public static Type[] GetExpandedGenericArguments(this Type t) {
var expanded = new Type[] { };
for(var skip = 1; t.TypeIs(VariadicType) ? true : skip-->0;) {
var args = skip>0 ? t.GetGenericArguments() : new[] { t };
if(args.Length>0) {
var length = args.Length-skip;
var temp = new Type[length+expanded.Length];
Array.Copy(args, skip, temp, 0, length);
Array.Copy(expanded, 0, temp, length, expanded.Length);
expanded=temp;
t=args[0];
}
}
return expanded;
}
}
}
For this implementation, I choosed not to break the compile-time type checking, so we do not have a constructor or a factory with the signature like params object[] to provide values; instead, use a fluent pattern of method V for mass object instantiation to keep type can be statically type checked as much as possible.

Categories