Tuesday, September 18, 2007

Impersonating data types

I've already talked about things I'm missing in C#/CLR (here and here). I'd like to add a new concept I would call "impersonation".

Let's start with a simple example:

Say I have a method that calculates the sum of some array of doubles (double[]), like so:

public static double Sum(double[] list)
{
double sum = 0.0;
for (int i = 0; i < list.Length; i++)
{
sum += list[i];
}
return sum;
}

Now I would like to use this method with an input that is not an array of doubles, but some other list of double values (say List<double>, a RowCollection, whatever).


The straight-forward solution is to change the Sum method to receive a collection instead of an array, or make it a template method. But that's when I can change it! What if the method belongs to some class that is not under my jurisdiction?


In this case, the only solution I can think of is to create a whole new array of doubles based on the collection you want to work with. But of course, that's not what I want! First, it costs time and memory. Second, if the Sum method would also change the actual values in the array - you're lost. In my case, it's the first restriction that bugs me.


If the input variable was something else than an array (some class), in most cases you would be able to solve it by inheriting from it and feeding the child class to the method. But then again it wouldn't work for all cases. First because the lack of multiple inheritance (sigh) could restrain you from such solution. Second, in the case the input variable is of some sealed type.


My solution (proposal) - impersonation.


A possible implementation would be an attribute on the class that indicates to the compiler that an object of this type could be used to substitute some other type. For example:

[Impersonate(typeof(double[]))]
public class MyCollection
{
// Implement the parts of double[] you are going to need
}

 


Note that in theory, one could implement in MyCollection only those parts of Array that might indeed be called. Then the call to the method could be done as so:

MyCollection myCollection = new MyCollection();
double sum = Sum(myCollection);

 


And, of course, the compiler should be able to understand the attribute and not generate any errors. Unless, of course, the Sum method uses some features of Array that are not implemented in MyCollection .


Lastly, I would allow multiple impersonations on the same class.

No comments: