What are the best approaches to implementing monads in C#? Are there particular implementation-strategies or is every monad differently implemented from the other?
To answer the question instead of just commenting on it, Linq is probably the foremost method of performing monadic transformations in C#. A Linq method chain is nothing more than a lazily-evaluated, ordered set of list-processing operations.
Linq, of course, is not rocket science; more than your average college-level programming course, but still. It's a series of extension methods that each produce a placeholder enumerable (the monad) containing the logic they should perform, and a reference to their source of data (which can be another monadic encapsulation). You can, and many do, add additional extensions to the basic Linq library to fill holes in the functionality or perform custom actions that meet specific needs.
You can also create your own monadic method chain frameworks, to do practically anything. Pretty much any framework or library described as having a "fluent" coding interface is a monad-based library. There are fluent unit test asserters, fluent ORM configurations, even fluent domain-UI mapping extensions.
Implementing a monadic library in C# is usually done using a static class and static methods, which make use of one or more monadic types which are inaccessible from outside their intended usage. For instance, here is a basic monadic library that performs integer addition and subtraction:
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
int theValue;
internal Monad(int input) { theValue = input; }
public Monad Add(int input){ return new Monad(theValue + input); }
public Monad Subtract(int input){ return new Monad(theValue - result); }
public int Value { get { return theValue; } }
}
}
...
//usage
var result = MonadicArithmetic.Take(1).Add(2).Subtract(1).Value; //2
Obviously this is very basic, and all operations are performed "eagerly". If those operations were complex, this may not be optimal, so instead, let's perform them "lazily":
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
//Change the "value keeper" into a Func that will return the value;
Func<int> theValue;
//the constructor now turns the input value into a lambda
internal Monad(int input) { theValue = ()=>input; }
//and another constructor is added for intra-class use that takes a lambda
private Monad(Func<int> input) { theValue = input; }
//And now the methods will create new lambdas that call the existing lambdas
public Monad Add(int input){ return new Monad(()=>theValue() + input); }
public Monad Subtract(int input){ return new Monad(()=>theValue() - input); }
//Finally, our Value getter at the end will evaluate the lambda, unwrapping all the nested calls
public int Value { get { return theValue(); } }
}
}
Same usage, except no operations will be performed until a concrete Value is requested by consuming code:
//Each call just adds a shell to the nested lambdas
var operation = MonadicArithmetic.Take(1).Add(2).Subtract(1);
...
//HERE's the payoff; the result is not evaluated till the call to Value_get() behind the scenes of this assignment.
var result = operation.Value;
However, there's a problem with this. The methods simply take the input values, and reference them in a lambda. The problem is that the values' scope is dependent on the containing method (meaning they don't live long enough for the lambda to be evaluated). When the Value() getter is called, the lambda will be evaluated, and all of these out-of-scope variables will be referenced. Instead, we should persist the values in something that will live at least as long as the lambdas do. The monad is the obvious option. Here is a probable solution:
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
//Our value keeper is now a pure function that requires no external closures
Func<Func<int>, int, int> operation;
//and we add two new private fields;
//a hook to a lambda that will give us the result of all previous operations,
Func<int> source;
//... and the value for the current operation.
private int addend;
//our constructor now takes the value, stores it, and creates a simple lambda
internal Monad(int input) { addend = input; operation = ()=>addend; }
//and our private constructor now builds a new Monad from scratch
private Monad(Func<int> prevOp, Func<Func<int>, int, int> currOp, int input)
{
source = prevOp,
operation = currOp,
addend = input;
}
//The methods will create new Monads that take the current Monad's value getter,
//keeping the current Monad in memory.
public Monad Add(int input)
{
return new Monad(this.Result, (f,i)=>f()+i, input);
}
public Monad Subtract(int input)
{
return new Monad(this.Result, (f,i)=>f()-i, input);
}
//And we change our property to a method, so it can also
//be used internally as a delegate
public int Result() { return operation(source, addend); }
}
}
//usage
var operations = MonadicArithmetic.Take(1).Add(3).Subtract(2);
//There are now 3 Monads in memory, each holding a hook to the previous Monad,
//the current addend, and a function to produce the result...
...
//so that here, all the necessary pieces are still available.
var result = operations.Result();
This is the basic pattern for a monadic library. The static method that starts the whole thing can be an extension method, which is the style Linq uses. The root of the method chain becomes the first value:
//using an "identity function" to convert to a monad
var operations = 1.AsMonad().Add(2).Subtract(3);
//performing the conversion implicitly from an overload of Add()
var operations = 1.Add(2).Subtract(3);
Linq for objects is particularly elegant in that its libraries are extension methods that take an IEnumerable and return an IEnumerable, so the conversion process is handled without any overloading or explicit method calls. However, IQueryable objects, which hide translatable expression trees, ARE a new idea in .NET 3.5, and you DO have to explicitly convert a collection to an IQueryable, via the AsQueryable() method.
Related
I have this code (its just part, entire code works just fine):
internal static Rule<IWorkflowModel> Get()
{
var rule = new Rule<IWorkflowModel>("Argument Naming Rule", RuleId, Inspect)
{
DefaultErrorLevel = System.Diagnostics.TraceLevel.Warning,
RecommendationMessage = Recommendation
};
return rule;
}
private static InspectionResult Inspect(IWorkflowModel workflowModel, Rule ruleInstance)
{
I am trying to understand, how can we pass Inspect static method as parameter in line 3, without adding parameters to itself (like Inspect(paramA, paramB)?
I can guess it takes both Rule and IWorkflowModel objects from the rule created itself (line 3). But trying to figure out some logic/rule behind it.
Edit
This is Rule<T> class from metadata
namespace UiPath.Studio.Activities.Api.Analyzer.Rules
{
public sealed class Rule<T> : Rule where T : IInspectionObject
{
public Rule(string ruleName, string ruleId, Func<T, Rule, InspectionResult> inspectionFunction);
public Func<T, Rule, InspectionResult> Inspect { get; }
}
}
You're passing the function, not invoking it. This allows a different piece of code to invoke the function later, supplying the arguments.
The way this is done in C# is through delegates (since about .NET 3.5, instead of using custom delegate types, you will probably want to use Action and Func respectively). You can think of a delegate as a single-method interface - it's basically a bridge between object-oriented and true functional programming.
In older code, this was mainly used in events and callbacks. Today, as C# gets more and more functional, it's getting rather common for abstract functions to accept functions as arguments; LINQ was probably the first big example. You supply your own behaviour to other functions. You want to filter a collection? Just pass a function that does the filtering (col.Where(i => i.Name.Length > 3)).
To show you a possible way of implementing what you're seeing in your code:
public class Rule<T> : Rule
{
private readonly Func<T, Rule, InspectionResult> _inspect;
public Rule(string name, string ruleId, Func<T, Rule, InspectionResult> inspect)
: base(name, ruleId)
{
_inspect = inspect;
}
public InspectionResult Inspect(T model) => _inspect(this, model);
}
Note that when Rule<T> calls the delegate, it must supply all of the arguments.
Of course, the actual behaviour of the caller can be essentially arbitrary. The point is that you're passing a behaviour to someone else. Delegates are a very simple and quick way of doing that, especially combined with anonymous functions and all that.
Reading a Previous SO Question I was confused to find Eric Lippert saying that an interface cannot be defined in C# for all Monads, using an implementation as below:
typeInterface Monad<MonadType<A>>
{
static MonadType<A> Return(A a);
static MonadType<B> Bind<B>(MonadType<A> x, Func<A, MonadType<B>> f);
}
My problem is all the problems listed in the question seem to have easy solutions:
no "higher kinded types" => use parent interfaces
no static method in interface. => why use static?! just use instance methods
Monad is a pattern allowing chaining of operations on wrapped types
it seems easy to define a C# interface for all Monads allowing us to write a generic class for all monads
Where's the problem?
using System;
using System.Linq;
public class Program
{
public static void Main()
{//it works, where's the problem?
new SequenceMonad<int>(5)
.Bind(x => new SequenceMonad<float>(x + 7F))
.Bind(x => new SequenceMonad<double>(x + 5D))
;
}
interface IMonad<T>{
IMonad<T> Wrap(T a);
IMonad<U> Bind<U>(Func<T, IMonad<U>> map);
T UnWrap();//if we can wrap we should be able to unwrap
}
class GenericClassForAllMonads<T>
{//example writing logic for all monads
IMonad<U> DoStuff<U>(IMonad<T> input, Func<T, IMonad<U>> map)
{ return map(input.UnWrap()); }
}
class SequenceMonad<T> : IMonad<T> where T:new()
{//specific monad implementation
readonly T[] items;//immutable
public SequenceMonad(T a)
{
Console.WriteLine("wrapped:"+a);
items = new[] { a };
}
public IMonad<B> Bind<B>(Func<T, IMonad<B>> map)
{ return map(UnWrap()); }
public T UnWrap()
{ return items == null? default(T) : items.FirstOrDefault(); }
public IMonad<T> Wrap(T a)
{
Console.WriteLine("wrapped:"+a);
return new SequenceMonad<T>(a);
}
}
}
it seems easy to define a C# interface for all monads. Where's the problem?
Your proposal is:
interface IMonad<T>
{
IMonad<T> Wrap(T a);
IMonad<U> Bind<U>(Func<T, IMonad<U>> map);
}
I've omitted the "unwrap" because the existence of an extraction operation is not a requirement of a monad. (Many monads have this operation, but not all do. If you require an extract operation, you are probably actually using a comonad.)
You ask why this is wrong. This is wrong in several ways.
The first way it is wrong is: there is no way to create a new instance of the monad via Wrap without already having an instance! You have a chicken-and-egg problem here.
The "wrap" or "unit" or "return" operation -- whatever you want to call it -- is logically a static factory; it's how you make a new instance of the monad. It's not an operation on an instance. It is a requirement of a static method on a type. (Or, the requirement that a type implement a particular constructor, which is effectively the same thing. Either way, it is not supported in C# at this time.)
Let's eliminate Wrap from consideration in the next point. Why is Bind wrong?
The second way it is wrong is you do not have the right restrictions in place. Your interface says that a monad of T is a thing that provides a bind operation that returns a monad of U. But that is not restrictive enough! Suppose we have a monad Maybe<T> : IMonad<T>. Now suppose we have this implementation:
class Wrong<T> : IMonad<T>
{
public IMonad<U> Bind<U>(Func<T, IMonad<U>> map)
{
return new Maybe<U>();
}
}
That satisfies the contract, which tells us that the contract is not the real monad contract. The monad contract should be that Wrong<T>.Bind<U> returns Wrong<U>, not IMonad<U>! But we have no way of expressing in C# "bind returns an instance of the class which defines bind".
Similarly it is wrong because the Func that is provided by the caller must be required to return Wrong<U>, not IMonad<U>. Suppose we have a third monad, say, State<T>. We could have
Wrong<Frog> w = whatever;
var result = w.Bind<Newspaper>(t=>new State<Newspaper>());
And now this is all messed up. Wrong<T>.Bind<U> must take a function that returns some Wrong<U> and must itself return Wrong<U> of the same type, but this interface allows us to have a bind that takes a function that returns State<Newspaper> but the bind returns Maybe<Newspaper>. This is a total violation of the monad pattern. You have not captured the monad pattern in your interface.
The C# type system is not strong enough to express the constraint "when the method is implemented it must return an instance of the class that did the implementation". If C# had a "this_type" compile-time annotation then Bind could be expressed as an interface, but C# does not have that annotation.
I'm writing a Linked List program in C# because I want to test how I feel about the language and I'm running into some serious difficulty. I'm trying to implement a Map method that functions like a Haskell map function (code below for both). However, I'm getting the error messages:
main.cs(43,66): error CS0029: Cannot implicitly convert type `void' to `MainClass.LinkedList<U>'
main.cs(43,33): error CS1662: Cannot convert `lambda expression' to delegate type `System.Func<MainClass.LinkedList<U>>' because some of the return types in the block are not implicitly convertible to the delegate return type
The relevant code in question:
Ideal Haskell code:
map :: [a] -> (a -> b) -> [b]
map (x:[]) f = (f x) : []
map (x:xs) f = (f x) : (map xs f)
C# code:
public class LinkedList<T> where T: class
{
public T first;
public LinkedList<T> rest;
public LinkedList(T x) {this.first = x;}
public void Join(LinkedList<T> xs)
{
Do(this.rest, ()=>this.rest.Join(xs), ()=>Assign(ref this.rest, xs));
}
public LinkedList<U> Map<U>(Func<T, U> f) where U: class
{
return DoR(this.rest, ()=>new LinkedList<U>(f(this.first)).Join(this.rest.Map(f)), ()=>new LinkedList<U>(f(this.first)));
}
public static void Assign<T>(ref T a, T b)
{
a = b;
}
public static U DoR<T, U>(T x, Func<U> f, Func<U> g)
{
if (x!=null) {return f();}
else {return g();}
}
public static void Do<T>(T x, Action f, Action g)
{
if (x != null) {f();}
else {g();}
}
While Assign, DoR (short for Do and Return), and Do seem like they're "code smell", they're what I came up with for trying to not write
if (x != null) {f();}
else {g();}
type statements (I'm used to patternmatching). If anybody has any better ideas, I'd love to know them, but mostly I'm concerned with the highlighted problem.
Starting with your immediate problem: the basic issue here is that you're mixing and matching lambda expressions that have either void return type or an actual return type. This can be addressed by changing your Join() method so that it returns the list used to call Join():
public LinkedList<T> Join(LinkedList<T> xs)
{
Do(this.rest, () => this.rest.Join(xs), () => Assign(ref this.rest, xs));
return this;
}
An alternative way would be to have a statement body lambda in the Map<U>() method that saves the new list to a variable and then returns that. But that adds a lot more code than just changing the Join() method, so it seems less preferable.
That said, you seem to be abusing C# a bit here. Just as when writing code in a functional language, one should really make an effort to write real functional code, in the manner idiomatic to that language, so too should one make an effort when writing C# code to write real imperative code, in the manner idiomatic to C#.
Yes, C# has some functional-like features in it, but they don't generally have the same power as the features found in real functional languages, and they are intended to allow C# programmers to get the low-hanging fruit of functional styles of code without having to switch languages. One particular thing also to be aware of is that lambda expressions generate a lot more code than normal C# imperative code.
Sticking to more idiomatic C# code, the data structure you're implementing above can be written much more concisely, and in a manner that creates much more efficient code. That would look something like this:
class LinkedList<T>
{
public T first;
public LinkedList<T> rest;
public LinkedList(T x) { first = x; }
public void Join(LinkedList<T> xs)
{
if (rest != null) rest.Join(xs);
else rest = xs;
}
public LinkedList<U> Map<U>(Func<T, U> f) where U : class
{
LinkedList<U> result = new LinkedList<U>(f(first));
if (rest != null) result.Join(rest.Map(f));
return result;
}
}
(For what it's worth, I don't see the point of the generic type constraint on your Map<U>() method. Why restrict it like that?)
Now, all that said, it seems to me that if you do want a functional-style linked-list implementation in C#, it would make sense to make it an immutable list. I'm not familiar with Haskell, but from my limited use of functional languages generally, I have the impression that immutability is a common feature in functional language data types, if not enforced 100% (e.g. XSL). So if trying to reimplement functional language constructs in C#, why not follow that paradigm?
See, for example, Eric Lippert's answer in Efficient implementation of immutable (double) LinkedList. Or his excellent series of articles on immutability in C# (you can start here: Immutability in C# Part One: Kinds of Immutability), where you can get ideas for how to create various immutable collection types.
In browsing Stack Overflow for related posts, I found several that, while not directly applicable to your question, may still be of interest (I know I found them very interesting):
how can I create a truly immutable doubly linked list in C#?
Immutable or not immutable?
Doubly Linked List in a Purely Functional Programming Language
Why does the same algorithm work in Scala much slower than in C#? And how to make it faster?
Converting C# code to F# (if statement)
I like that last one mainly for the way that in both the presentation of the question itself and the replies (answers and comments) help illustrate well why it's so important to avoid trying to just transliterate from one language to another, and instead to really try to become familiar with the way a language is designed to be used, and how common data structures and algorithms are represented in a given language, idiomatically.
Addendum:
Inspired by Eric Lippert's rough draft of an immutable list type, I wrote a different version that includes the Join() method, as well as the ability to add elements at the front and end of the list:
abstract class ImmutableList<T> : IEnumerable<T>
{
public static readonly ImmutableList<T> Empty = new EmptyList();
public abstract IEnumerator<T> GetEnumerator();
public abstract ImmutableList<T> AddLast(T t);
public abstract ImmutableList<T> InsertFirst(T t);
public ImmutableList<T> Join(ImmutableList<T> tail)
{
return new List(this, tail);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class EmptyList : ImmutableList<T>
{
public override ImmutableList<T> AddLast(T t)
{
return new LeafList(t);
}
public override IEnumerator<T> GetEnumerator()
{
yield break;
}
public override ImmutableList<T> InsertFirst(T t)
{
return AddLast(t);
}
}
abstract class NonEmptyList : ImmutableList<T>
{
public override ImmutableList<T> AddLast(T t)
{
return new List(this, new LeafList(t));
}
public override ImmutableList<T> InsertFirst(T t)
{
return new List(new LeafList(t), this);
}
}
class LeafList : NonEmptyList
{
private readonly T _value;
public LeafList(T t)
{
_value = t;
}
public override IEnumerator<T> GetEnumerator()
{
yield return _value;
}
}
class List : NonEmptyList
{
private readonly ImmutableList<T> _head;
private readonly ImmutableList<T> _tail;
public List(ImmutableList<T> head, ImmutableList<T> tail)
{
_head = head;
_tail = tail;
}
public override IEnumerator<T> GetEnumerator()
{
return _head.Concat(_tail).GetEnumerator();
}
}
}
The public API is a little different from Eric's. You enumerate it to access the elements. The implementation is different as well; using a binary tree was how I enabled the Join() method.
Note that with the interface IEnumerable<T> implemented, one way to implement the Map<U>() method is to not do it at all and instead just use the built-in Enumerable.Select():
ImmutableList<T> list = ...; // whatever your list is
Func<T, U> map = ...; // whatever your projection is
IEnumerable<U> mapped = list.Select(map);
As long as the map function is relatively inexpensive, that would work fine. Any time mapped is enumerated, it will re-enumerate list, applying the map function. The mapped enumeration remains immutable, because it's based on the immutable list object.
There are probably other ways to do it (for that matter, I know of at least one other), but the above is what made the most sense to be conceptually.
Is it possible to template methods for any kind of integer size ?
To illustrate, imagine this very trivial example (the body of the method is not important in my question):
public int Mul(int a, int b) {
return a*b;
}
Now, I want the same method that supports any kind of integer (excluding BigInteger of course). I have to write all variants :
public long Mul(long a, long b) {
return a*b;
}
public ulong Mul(ulong a, ulong b) {
return a*b;
}
public short Mul(short a, short b) {
return a*b;
}
public ushort Mul(ushort a, ushort b) {
return a*b;
}
public byte Mul(byte a, byte b) {
return a*b;
}
While this example is very trivial and it's not actually a problem to duplicate, if I have more complex algorithms like this (replicate for all integer kinds):
public static IEnumerable<long> GetPrimesFactors(this long number)
{
for (long i = 2; i <= number / 2; i++)
{
while (number % i == 0)
{
yield return i;
number /= i;
}
}
yield return number;
}
it introduces a maintenance risk as there is duplicated code and logic (coding integrists would say this is the evil to have same logic at multiple place).
Some of you may suggest to implements the long version and cast the result, but having to ask consumer code to cast can be confusing and reduce readability :
void SomeMethod(IEnumerable<int> valuesToProcess)
{
foreach(int value in valuesToProcess) { Console.WriteLine(value); }
}
void Main()
{
int i = 42;
SomeMethod(((long)i).GetPrimesFactors().Select(l=>(int)l));
SomeMethod(GetPrimesFactors(i));
long l = 42L;
SomeMethod(l.GetPrimesFactors().Select(l=>(int)l));
}
When I see the definition of the interface IEnumerable<T>, and especially the definitions of Sum method overloads :
public static decimal? Sum(this IEnumerable<decimal?> source);
public static decimal Sum(this IEnumerable<decimal> source);
public static double? Sum(this IEnumerable<double?> source);
public static double Sum(this IEnumerable<double> source);
public static float? Sum(this IEnumerable<float?> source);
public static float Sum(this IEnumerable<float> source);
public static int? Sum(this IEnumerable<int?> source);
public static int Sum(this IEnumerable<int> source);
public static long? Sum(this IEnumerable<long?> source);
public static long Sum(this IEnumerable<long> source);
I conclude that it's not possible... that's why MS has to implement all overloads.
Does anyone have any tips for designing general purpose integer methods without having to duplicate logic ?
There is no clean high performance solution. The choices I can think of are:
Manually duplicate the code (fast and redundant)
Automatically duplicate the code with a code generator (fast but a bit ugly). One .net numerics library went that way, but I don't remember its name.
Use some form of indirection, such as MiscUtil's Operator class, or the DLR (slow)
The arithmetic helper struct. I'm not sure how good the performance is, but you can try.
Generic methods representing operators:
These were my first idea. The issue is how to implement them. MiscUtil does this by calling a delegate stored in a static field.
static Func<T,T,T> _multiply;
public static T Multiply(T n1,T n2)
{
return _multiply(n1, n2);
}
One point to note here, is that you should avoid a static constructor, since its mere existence slows down static field access.
But that involves an indirect call, and that's expensive. I next tried to improve this by manually specializing for certain known types:
public static T Multiply(T n1,T n2)
{
if(typeof(T)==typeof(int))
return (T)(object)((int)(object)n1*(int)(object)n2);
...
return _multiply(n1, n2);
}
The JIT compiler is smart enough to realize which of those if cases it has to take, and will remove them. While that improved performance, it bloated the IL representation of the methods. And the JIT compiler is not smart enough to inline those method now, since their IL representation is long, and the inline heuristic only looks at the IL length of a method, not its machine code length. I don't remember if these casts cause boxing, or if the JITter was smart enough to optimize that out. Still the lack of inlining is too costly.
How 4) works:
First create an interface that contains the basic operations you need(arithmetic operators,...):
interface IArithmetic<T>
{
T Multiply(T n1,T n2);
}
Implement it for each type you need with a struct:
public struct Int32Arithmetic:IArithmetic<Int32>
{
Int32 Multiply(Int32 n1,Int32 n2)
{
return n1*n2;
}
}
Then make most of your actual code generic, and pass in an arithmetic helper:
internal T MyOperation<T,TArithmetic>(T n1, T n2)
where TArithmetic:struct,IArithmetic<T>
{
return default(TArithmetic).Multiply(n1,n2);
}
And if you want a clean interface for multiple types, create a thin overloaded wrapper forwarding to the generic method:
public Int32 MyOperation(Int32 n1,Int32 n2)
{
return MyOperation<Int32,Int32Arithmetic>(n1, n2);
}
This might be fast, because generics get specialized for each value type. It uses no indirections and the method bodies in IL don't get too long, so inlining is possible. But I haven't tried this myself yet.
Consider the DLR:
static void Main(string[] args)
{
int i = Mul(2, 4);
Console.WriteLine(i);
Console.Read();
}
static dynamic Mul(dynamic x, dynamic y)
{
return x * y;
}
Performance is to be determined (I'd expect it to be slower than straight overloads), but readability is much nicer. Could get a little hairy if you provide types that don't implement the required operators or different types that cause values to truncate.
Updated from comment:
If performance is so critical, then it sounds like you have already chosen the trade-off between duplicating/readability and the performance you seek. Code-gen it and move on. Any maintenance issues from a few pieces of extra code are likely dwarfed by the maintenance of the performance itself.
Well, what you could do is generate the duplicated code during your build process using, for example, T4.
public T Mul<T>(T a, T b){
dynamic x = a;
dynamic y = b;
return (T)x*y;
}
I once tried so implement something similar using CodeDom to generate an assembly during runtime and dynamically load it. This works rather well, but has some limitations. For example, your environment might not allow you to dynamically compile assemblies and there is the big one: performance. Although the "calculator"-class is only generated once, the overhead of calling a virtual method actually doubles the time necessary for the calculation.
You could give it a try to see how it would perform in your environment, I just lay out the classes (since this was a long time ago and I don't have the code anymore).
interface ICalculator<T> {
T Add(T left, T right);
T Multiply(T left, T right);
}
internal static class Calculator<T> {
static ICalculator<T> instance;
static Calculator() {
Type type = typeof(T);
// 1. Use CodeDom to design a class that implements ICalculator<T> using the
// builtin +,-,*,/ operators
// 2. Compile assembly in memory
// 3. Load assembly and create an instance of the ICalculator<T> class
Type concreteType = GetTypeFromDynamicAssembly(); // Get this from the assembly.
instance = Activator.CreateInstance(concreteType) as ICalculator<T>;
}
public static T Add(T left, T right) {
return instance.Add(left, right);
}
}
class MyClassUsingGenericMathType<T> {
T Sum(params T[] values) {
T sum = default(T);
foreach (T value in values) {
sum = Calculator<T>.Add(sum, value);
}
return sum;
}
}
The idea is that you dynamically built the implementation first time it is used (the static constructor is invoked then), after that the Calculator methods directly call the corresponding operator of the numeric type you are using. As I said, I remember that this adds an overhead everytime an operation is performed, but I never analyzed whether there is a potential for speeding up the process using some Compiler-attributes.
Another thing: using a type that doesn't implement the corresponding operators would cause a runtime-exception rather than a compile error. So it's far from perfect.
I currently have a switch statement that runs around 300 odd lines. I know this is not as giant as it can get, but I'm sure there's a better way to handle this.
The switch statement takes an Enum that is used to determine certain properties that pertain to logging. Right now the problem sets in that it is very easy to leave out an enumeration value and that it will not be given a value as it is not in the switch statement.
Is there an option one can use to ensure that every enumeration is used and given a custom set of values it needs to do its job?
EDIT:
Code sample as requested: (This is simplistic, but shows exactly what I mean. Also an Enumeration would exist with the below values.)
internal void GenerateStatusLog(LogAction ActionToLog)
{
switch (ActionToLog)
{
case LogAction.None:
{
return;
}
case LogAction.LogThis:
{
ActionText = "Logging this Information";
LogText = "Go for it.";
break;
}
}
// .. Do everything else
}
EDIT
I thought this over again, looked around in related questions in SO, and I wrote some code. I created a class named AdvancedSwitch<T>, which allows you to add cases and exposes a method to evaluate a value and lets you specify values that it should check for existence.
This is what I came up with:
public class AdvancedSwitch<T> where T : struct
{
protected Dictionary<T, Action> handlers = new Dictionary<T, Action>();
public void AddHandler(T caseValue, Action action)
{
handlers.Add(caseValue, action);
}
public void RemoveHandler(T caseValue)
{
handlers.Remove(caseValue);
}
public void ExecuteHandler(T actualValue)
{
ExecuteHandler(actualValue, Enumerable.Empty<T>());
}
public void ExecuteHandler(T actualValue, IEnumerable<T> ensureExistence)
{
foreach (var val in ensureExistence)
if (!handlers.ContainsKey(val))
throw new InvalidOperationException("The case " + val.ToString() + " is not handled.");
handlers[actualValue]();
}
}
You can consume the class this way:
public enum TrafficColor { Red, Yellow, Green }
public static void Main()
{
Console.WriteLine("Choose a traffic color: red, yellow, green?");
var color = (TrafficColor)Enum.Parse(typeof(TrafficColor), Console.ReadLine());
var result = string.Empty;
// Creating the "switch"
var mySwitch = new AdvancedSwitch<TrafficColor>();
// Adding a single case
mySwitch.AddHandler(TrafficColor.Green, delegate
{
result = "You may pass.";
});
// Adding multiple cases with the same action
Action redAndYellowDelegate = delegate
{
result = "You may not pass.";
};
mySwitch.AddHandler(TrafficColor.Red, redAndYellowDelegate);
mySwitch.AddHandler(TrafficColor.Yellow, redAndYellowDelegate);
// Evaluating it
mySwitch.ExecuteHandler(color, (TrafficColor[])Enum.GetValues(typeof(TrafficColor)));
Console.WriteLine(result);
}
With the creative use of anonymous delegates, you can easily add new cases to your "switch block". :)
Not that you can also use lambda expressions, and lambda blocks, eg () => { ... } instead of delegate { ... }.
You can easily use this class instead of the long switch blocks.
Original post:
If you use Visual Studio, always create swich statements with the switch code snippet. Type switch press tab twice, and it auto-generates all the possibilities for you.
Then, add a default case to the end which throws an exception, that way when testing your app you will notice that there is an unhandled case, instantly.
I mean something like this:
switch (something)
{
...
case YourEnum.SomeValue:
...
break;
default:
throw new InvalidOperationException("Default case reached.");
}
Well, there's throwing in the default case... There's no edit / compile time construct other than that.
However Strategy, Visitor and other patterns related to them may be appropriate if you choose to do it at run time.
Sample code will help with getting the best answer.
EDIT: Thanks for the sample. I still think it needs a bit of fleshing out as you dont cover whether there are some parameters that only apply to some cases etc.
Action is often used as an alias for the Command pattern and the fact that your Enum is called LogAction signifies that each value carries with it a behavior - be that implied (you stick appropriate code in a case) or explicit (in the specific Command hierarchy class).
Thus it looks to me like a usage of the Command pattern is appropriate (though your sample doesnt prove it) - i.e., have a class (potentially a hierarchy using constructor overloads or any other [set of] factory mechanisms) that keeps the state associated with the request along with the specific behaviour. Then, instead of passing an Enum value, create an appropriate LogCommand instance to the logger, which just invokes it (potentially passing a Log Sink 'receptacle' which the Command can log into). Otherwise you're poking random subsets of parameters in different places.
SEEALSO related posts:
C# - Is there a better alternative than this to ‘switch on type’?
Replace giant switch statement with what?
One possible solution is to use a SortedDictionary:
delegate void EnumHandler (args);
SortedDictionary <Enum, EnumHandler> handlers;
constructor
{
handlers = new SortedDictionary <Enum, EnumHandler> ();
fill in handlers
}
void SomeFunction (Enum enum)
{
EnumHandler handler;
if (handlers.TryGetValue (enum, out handler))
{
handler (args);
}
else
{
// not handled, report an error
}
}
This method does allow you to replace the handlers dynamically. You could also use a List as the value part of the dictionary and have multiple handlers for each enum.
Try to use reflection.
Decorate enum options with attributes that holds associated value and return this value.
Create static class of constants and use reflection for mapping enum-option to constant by name
hope this will help
Some times storing the options in a map is a good solution, you can externalize the configuration to a file too, not sure if it applies to your application.
Long code example here, and the final generic code is a little heavy (EDIT have added an extra example that eliminates the need for the angle brackets at the expense of some final flexibility).
One thing that this solution will give you is good performance - not quite as good as a straightforward switch statement, but each case statement becomes a dictionary lookup and method invocation, so still pretty good. The first call will get a performance penalty, however, due to the use of a static generic that reflects on initialisation.
Create an attribute and generic type as follows:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DynamicSwitchAttribute : Attribute
{
public DynamicSwitchAttribute(Type enumType, params object[] targets)
{ Targets = new HashSet<object>(targets); EnumType = enumType; }
public Type EnumType { get; private set; }
public HashSet<object> Targets { get; private set; }
}
//this builds a cache of methods for a given TTarget type, with a
//signature equal to TAction,
//keyed by values of the type TEnum. All methods are expected to
//be instance methods.
//this code can easily be modified to support static methods instead.
//what would be nice here is if we could enforce a generic constraint
//on TAction : Delegate, but we can't.
public static class DynamicSwitch<TTarget, TEnum, TAction>
{
//our lookup of actions against enum values.
//note: no lock is required on this as it is built when the static
//class is initialised.
private static Dictionary<TEnum, TAction> _actions =
new Dictionary<TEnum, TAction>();
private static MethodInfo _tActionMethod;
private static MethodInfo TActionMethod
{
get
{
if (_tActionMethod == null)
{
//one criticism of this approach might be that validation exceptions
//will be thrown inside a TypeInitializationException.
_tActionMethod = typeof(TAction).GetMethod("Invoke",
BindingFlags.Instance | BindingFlags.Public);
if (_tActionMethod == null)
throw new ArgumentException(/*elided*/);
//verify that the first parameter type is compatible with our
//TTarget type.
var methodParams = _tActionMethod.GetParameters();
if (methodParams.Length == 0)
throw new ArgumentException(/*elided*/);
//now check that the first parameter is compatible with our type TTarget
if (!methodParams[0].ParameterType.IsAssignableFrom(typeof(TTarget)))
throw new ArgumentException(/*elided*/);
}
return _tActionMethod;
}
}
static DynamicSwitch()
{
//examine the type TTarget to extract all public instance methods
//(you can change this to private instance if need be) which have a
//DynamicSwitchAttribute defined.
//we then project the attributes and the method into an anonymous type
var possibleMatchingMethods =
from method in typeof(TTarget).
GetMethods(BindingFlags.Public | BindingFlags.Instance)
let attributes = method.GetCustomAttributes(
typeof(DynamicSwitchAttribute), true).
Cast<DynamicSwitchAttribute>().ToArray()
where attributes!= null && attributes.Length == 1
&& attributes[0].EnumType.Equals(typeof(TEnum))
select new { Method = method, Attribute = attributes[0] };
//create linq expression parameter expressions for each of the
//delegate type's parameters
//these can be re-used for each of the dynamic methods we generate.
ParameterExpression[] paramExprs = TActionMethod.GetParameters().
Select((pinfo, index) =>
Expression.Parameter(
pinfo.ParameterType, pinfo.Name ?? string.Format("arg{0}"))
).ToArray();
//pre-build an array of these parameter expressions that only
//include the actual parameters
//for the method, and not the 'this' parameter.
ParameterExpression[] realParamExprs = paramExprs.Skip(1).ToArray();
//this has to be generated for each target method.
MethodCallExpression methodCall = null;
foreach (var match in possibleMatchingMethods)
{
if (!MethodMatchesAction(match.Method))
continue;
//right, now we're going to use System.Linq.Expressions to build
//a dynamic expression to invoke this method given an instance of TTarget.
methodCall =
Expression.Call(
Expression.Convert(
paramExprs[0], typeof(TTarget)
),
match.Method, realParamExprs);
TAction dynamicDelegate = Expression.
Lambda<TAction>(methodCall, paramExprs).Compile();
//now we have our method, we simply inject it into the dictionary, using
//all the unique TEnum values (from the attribute) as the keys
foreach (var enumValue in match.Attribute.Targets.OfType<TEnum>())
{
if (_actions.ContainsKey(enumValue))
throw new InvalidOperationException(/*elided*/);
_actions[enumValue] = dynamicDelegate;
}
}
}
private static bool MethodMatchesAction(MethodInfo method)
{
//so we want to check that the target method matches our desired
//delegate type (TAction).
//The way this is done is to fetch the delegate type's Invoke
//method (implicitly invoked when you invoke delegate(args)), and
//then we check the return type and parameters types of that
//against the return type and args of the method we've been passed.
//if the target method's return type is equal to or derived from the
//expected delegate's return type, then all is good.
if (!_tActionMethod.ReturnType.IsAssignableFrom(method.ReturnType))
return false;
//now, the parameter lists of the method will not be equal in length,
//as our delegate explicitly includes the 'this' parameter, whereas
//instance methods do not.
var methodParams = method.GetParameters();
var delegateParams = TActionMethod.GetParameters();
for (int i = 0; i < methodParams.Length; i++)
{
if (!methodParams[i].ParameterType.IsAssignableFrom(
delegateParams[i + 1].ParameterType))
return false;
}
return true;
}
public static TAction Resolve(TEnum value)
{
TAction result;
if (!_actions.TryGetValue(value, out result))
throw new ArgumentException("The value is not mapped");
return result;
}
}
Now do this in a Unit Test:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(1,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.BlahBlah)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Blip)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Bop)(this));
}
public enum Blah
{
BlahBlah,
Bloo,
Blip,
Bup,
Bop
}
[DynamicSwitchAttribute(typeof(Blah), Blah.BlahBlah)]
public int Method()
{
return 1;
}
[DynamicSwitchAttribute(typeof(Blah), Blah.Blip, Blah.Bop)]
public int Method2()
{
return 125;
}
So, given a value of TEnum, and your preferred 'action' type (in your code you would appear to be simply returning nothing and modifying the internal state of the class), you simply consult the DynamicSwitch<> class, ask it to resolve a target method, and then invoke it inline (passing the target object on which the method will be invoked as the first parameter).
I'm not really expecting any votes for this - it's a MAD solution to be honest (it does have the advantage of being able to be applied for any enum type, and even discreet values of type int/float/double, as well as supporting any delegate type) - so perhaps it's a bit of a sledgehammer!
EDIT
Once you have a static generic like this, angle-bracket hell ensues - so we want to try and get rid of them. A lot of the time, this is done by type inference on method parameters etc - but we have a problem here that we can't easily infer a delegate's signature without repeating the method call i.e. (args) => return.
However, you seem to require a method that takes no parameters and returns void, so you can close over this behemoth generic by fixing the delegate type to Action, and throw a fluid API into the mix as well (if that's your kind of thing):
public static class ActionSwitch
{
public class SwitchOn<TEnum>
{
private TEnum Value { get; set; }
internal SwitchOn(TEnum value)
{
Value = value;
}
public class Call<TTarget>{
private TEnum Value { get; set; }
private TTarget Target { get; set; }
internal Call(TEnum value, TTarget target)
{
Value = value;
Target = target;
Invoke();
}
internal void Invoke(){
DynamicSwitch<TTarget, TEnum, Action<TTarget>>.Resolve(Value)(Target);
}
}
public Call<TTarget> On<TTarget>(TTarget target)
{
return new Call<TTarget>(Value, target);
}
}
public static SwitchOn<TEnum> Switch<TEnum>(TEnum onValue)
{
return new SwitchOn<TEnum>(onValue);
}
}
Now add this to the test project:
[TestMethod]
public void TestMethod2()
{
//no longer have any angle brackets
ActionSwitch.Switch(Blah.Bup).On(this);
Assert.IsTrue(_actionMethod1Called);
}
private bool _actionMethod1Called;
[DynamicSwitch(typeof(Blah), Blah.Bup)]
public void ActionMethod1()
{
_actionMethod1Called = true;
}
Only issue with this (apart from the complexity of the solution :) ) is that you'd have to re-build this static wrapper type whenever you want to use a new type of target delegate for a dynamic switch elsewhere. You could generate a generic version based on the Action<...> and Func<...> delegates that incorporates TArg1, TArg(n) and TReturn (if Func<>) - but you'd end up writing a lot more code.
Perhaps I'll turn this into an article on my blog and do all of that - if I get the time!