You can only memoize a function if all its inputs are value types or immutable reference types, if it returns a value type or a new instance of the reference type, and if it has no side effects. Period.
Memorization depends on the deterministic mapping between inputs and outputs. Each call to F(a, b, c) , in which a, b, and c contain the same values, must return the same result so that memoning is possible.
If the parameter is a reference type, then although its value does not change, several calls to the function using it may lead to a different result. Trivial example:
public int MyFunction(MyType t) { return t.Value; } Console.WriteLine(MyFunction(t)); t.Value++; Console.WriteLine(MyFunction(t));
Similarly, if a function depends on an external value, then several calls to this function with the same parameters can return different results:
int Value = 0; public int MyFunction(int input) { return Value; } Console.WriteLine(MyFunction(1)); Value++; Console.WriteLine(MyFunction(1));
And heaven helps you if your memoized function does something other than return a value or a new reference type:
int Value = 0; public int MyFunction(int input) { Value++; return input; }
If you call this function 10 times, Value will be 10. If you reorganize it to use memoization, and then call it 10 times, Value will be 1.
You can begin to take the path of figuring out how to save memoize state so that you can fake a function that remembers the type of link. But what you really remember is a set of values that the function works on. Similarly, you can hack a memoized function that has side effects so that its side effects occur before recording. But this is all asking for trouble.
If you want to implement memoization in a function that takes a reference type, then a suitable approach is to reorganize the part of the function that only works with value types, and memoize this function, for example:
public int MyFunction(MyType t) { return t.Value + 1; }
:
public int MyFunction(MyType t) { return MyMemoizableFunction(t.Value); } private int MyMemoizableFunction(int value) { return value + 1; }
Any other approach to implementing memoization that you take either a) does the same, through more obscure means, or b) will not work.