So I've written a quick bit of code to help quickly convert between business objects and view models. Not to pimp my own blog, but you can find the details here if you're interested or need to know.
One issue I've run in to is that I have a custom collection type, ProductCollection, and I need to turn that in to a string[] in on my model. Obviously, since there is no default implicit cast, I'm getting an exception in my contract converter.
So, I thought I would write the next little bit of code and that should solve the problem:
public static implicit operator string[](ProductCollection collection) {
var list = new List<string>();
foreach (var product in collection)
{
if (product.Id == null)
{
list.Add(null);
}
else
{
list.Add(product.Id.ToString());
}
}
return list.ToArray();
}
However, it still fails with the same cast exception. I'm wondering if it has something to do with being in reflection? If so, is there anything that I can do here?? I'm open to architectural solutions, too!
First, the implicit operator allows for implcit conversions (no casting directive). explicit operators operate on casts.
Nonetheless, that isn't the real issue here. Operators are not polymorphic (they're overloaded, not overridden); that is, in order to take advantage of an overloaded operator, you must be referring to a class in the context of the class that defines it.
For example:
public class Foo
{
public static implicit operator Bar(Foo foo) { return new Bar(); }
}
public class Bar { }
...
void Baz()
{
Foo foo = new Foo();
Bar bar = foo; // OK
object baz = foo;
bar = baz; // won't compile, there's no defined operator at the object level
bar = (Bar)baz; // will compile, but will fail at runtime for the same reason
}
Without knowing what you're doing and how you're doing it, I can't offer much in the way of a meaningful alternative. Some ideas, however:
Override ToString (or use a common base class / interface for your entities with your own version if you don't want to use ToString) on your entities, then enumerate the collections generically to construct your string array
Provide a ToStringArray function on your collections (by way of a common base class or interface) that does something similar
The biggest point is not to use operators for this purpose; they won't help you.
Related
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.
Problem: I have 2 types which are result sets of 2 different procedures in DB:
Proc1Result, Proc2Result (We had to split them - but they are basically the same as comes for input/output)
I then decided that I could make use of an interface to switch between needed procedures on runtime - but this means I would need 1 common type to which i could convert Proc1Result and Proc2Result
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result) - I derived this class from one of the results:
public class DerivedClassForInterface : Proc1Result {}
Then I implemented explicit cast from the 2nd proc which works fine, but when I want to implement explicit cast from base class to derived class - it wont allow me (since it kinda already "does" - but it fails at runtime):
public class DerivedClassForInterface : Proc1Result
{
//ok - and works as expected
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
return new DerivedClassForInterface
{
...
};
}
//fail: 'user-defined' conversations to or from a base class are not allowed
public static explicit operator DerivedClassForInterface(Proc1Result v)
{
return new DerivedClassForInterface
{
...
};
}
}
so this works:
//result2 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result2;
//compiles - works as expected at runtime
but this does not:
//result1 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result1;
//compiles - conversation fails at runtime
So why I can not write my own explicit operator if you can not cast from base class to derived class?
Interesting that compiler allows me to cast from base to derived class, and yet it does not work at runtime.
Probably I will go just for simple functions which will do the "casting" for me. Anyone can suggest a better solution (keep in mind that I would like to keep "DerivedClassForInterface" to obey changes in "Proc1Result" (or "Proc2Result" - doesn't matter))
EDIT
#Peter Duniho - Here the types "Proc1Result" and "Proc2Result" are generated as results from stored procedures (linq2sql). I would like to have a code which I wont need to touch when output of those procedures change (since there are bunch of procedures we need to segment - and implementing new modules could and often does add more output).
Proc1 and Proc2 are basically same stored procedures (they require exactly the same input and provides same output (type-wise not data-wise)). Both of them work with different segments of data and are required to be separate.
Sorry for making this confusing (was at end of my working day...) and not clarifying - the question here actually is:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
Here is "Minimal, Complete, and Verifiable code example" (thanks for the link):
//results from stored procedures in database which got splitted appart (linq 2 sql)
class Proc1Result { }
class Proc2Result { }
//
class DerivedClassForInterface : Proc1Result
{
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
//this part would be exported in generic function
var derivedClassInstance = new DerivedClassForInterface();
var properties = v.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedClassInstance.GetType().GetProperty(property.Name);
if (propToSet.SetMethod != null) propToSet.SetValue(derivedClassInstance, property.GetValue(v));
}
return derivedClassInstance;
}
}
interface IProcLauncher
{
DerivedClassForInterface GetNeededData();
}
class ProcLauncher1 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc1Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class ProcLauncher2 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class Program
{
static void Main(string[] args)
{
bool causeInvalidCastException = true;
IProcLauncher procedureLauncher;
if (causeInvalidCastException) procedureLauncher = new ProcLauncher1();
else procedureLauncher = new ProcLauncher2();
var result = procedureLauncher.GetNeededData();
Console.WriteLine("I got here!");
}
}
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
I can solve this - let say - by just 1 generic function which will handle conversation for all cases, but the question is above in bold.
I implemented the converting the following way:
class BaseConverter
{
protected T Convert<T, X>(X result)
{
var derivedClassInstance = Activator.CreateInstance<T>();
var derivedType = derivedClassInstance.GetType();
var properties = result.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(derivedClassInstance, property.GetValue(result));
}
}
return derivedClassInstance;
}
protected List<T> Convert<T, X>(List<X> listResult)
{
var derivedList = new List<T>();
foreach (var r in listResult)
{
//can cope with this - since there will not ever be many iterations
derivedList.Add(Convert<T, X>(r));
}
return derivedList;
}
}
So interface implementation classes would inherit from it:
class ProcLauncher2 : BaseConverter, IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
//usage (works for single result or list if I need a list returned):
return Convert<DerivedClassForInterface, Proc2Result>(dataFromDb);
}
//other methods...
}
Yet - it is not clear for me - why there is already cast from base class to derived - if that does not work. Imo - it should not be there and throw error at compile time.
I don't understand your question very well. You seem to say that the compiler lets you write the code you posted, but that it fails at runtime. This isn't my experience. I get a compile-time error on the explicit conversion operation for the base class:
error CS0553: 'Derived.explicit operator Derived(Base1)': user-defined conversions to or from a base class are not allowed
Seems pretty clear to me. As for why you aren't allowed to write code like that, you'd have to ask the language designers to know for sure, but it seems like a reasonable restriction to me. There already is a safe, built-in conversion from any base class to a derived class of that base class, as long as the base class instance is in fact an instance of the derived class. It would be confusing and likely to lead to bugs if programmers were allowed to make additional conversions, never mind greatly complicate the language specification's rules for the casting/conversion operator.
As for the broader problem, I don't understand the approach you've chosen. You're designing the classes exactly upside-down from the way one would normally do this. If you have a number of classes that all have shared members, you want to be able to treat all those classes as the same in some context, and you want to be able to implement those shared members exactly once and share them among the other classes, you would put all those members in a single base class, and then derive all your various types from that class.
I don't even see how your current approach addresses this concern:
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result)
Since Proc2Result doesn't inherit Proc1Result, if Proc1Result changes, you'll have to go change Proc2Result to match anyway. And any other similar types. And the DerivedClassForInterface class. And you have to change all the explicit operators. How is that better?
I would think you would prefer something like:
class BaseClassForInterface
{
// declare all shared members here
}
class Proc1Result : BaseClassForInterface { ... }
class Proc2Result : BaseClassForInterface { ... }
Then, for each new Proc...Result class, you simply inherit the base class, no need to re-write the members, and the conversion from each Proc...Result class is trivial. You don't even need to use the casting/conversion operator; the language already knows how to implicitly convert from derived classes to base classes, because the derived classes are the base classes.
This is, in fact, the standard way to use OOP. It's one of the most fundamental features of any OOP language.
If that doesn't get you back on track, you'll need to improve the question, so that it's more clear what you are doing and why. You'll also need to provide a good Minimal, Complete, and Verifiable code example that clearly illustrates your question, explaining precisely what that code does and what you want it to do instead.
Addendum:
Thanks for the edit. Your question is a lot more specific and clear now. I still have questions, but at least I understand the real context.
It seems to me that you already understand most of the basic answer to your question:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
I.e. yes, I believe the language disallows this because there is already a built-in cast, and yes the exact approach you seek is doomed to not work.
As far as this part goes:
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
If I understand the first point, this is why you inherit one of the stored procedure types. So that you get the property declarations for free. Seems a little hacky to me, but I admit I do understand the motivation.
As I understand the third point above and your statement after in your post, you already know how you can write a generic method to do the conversion. E.g. something like:
DerivedClassForInterface ConvertToClassForInterface<T>(T t)
{
DerivedClassForInterface result = new DerivedClassForInterface();
Type resultType = typeof(DerivedClassForInterface);
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var propToSet = resultType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(result, property.GetValue(t));
}
}
return result;
}
I.e. essentially the code you show in your explicit operator (with some minor cleanup/optimization). Or maybe you aren't using the term "generic" literally, and just mean "general purpose". Obviously there's very little in the above that really benefits from the method being generic; you could just as easily use GetType() on the parameter, just as your explicit operator does.
Unfortunately, I don't know how the criteria "Got to be injectable" fits in here. Injectable, how? Do you mean you want to inject the code somewhere else? Or do you mean that the code needs to be compatible with an AOP system, or some other form of code injection applied to it?
Ignoring that part, which I don't understand, I would actually just leverage the compiler and runtime to do all the heavy lifting for me (including caching the reflection stuff, which in your code is going to be very slow). You could write a class like this:
class Wrapper
{
private dynamic _data;
public string Value { get { return _data.Value; } }
public Wrapper(dynamic data)
{
_data = data;
}
}
Given a couple of other classes like this:
class Result1
{
public string Value { get; set; }
}
class Result2
{
public string Value { get; set; }
}
Then you can use it like this:
Result1 r1 = new Result1 { Value = "result 1" };
Result2 r2 = new Result2 { Value = "result 2" };
Wrapper w1 = new Wrapper(r1), w2 = new Wrapper(r2);
Console.WriteLine("w1 result: " + w1.Value);
Console.WriteLine("w2 result: " + w2.Value);
I.e. just create an instance of Wrapper, passing the relevant object (in your case, this would be the generated type's from the stored procedure). The downside is, of course, that you do have to add properties to the Wrapper type to match your stored procedure. But I'm not convinced that's a bad thing. Even if you've somehow arranged it so that none of the rest of the code has to change, it's a relatively minor maintenance task.
And I suspect that altering the stored procedure requires changes elsewhere in the code anyway, to explicitly refer to the properties. Because after all, if the rest of the code is similarly completely agnostic regarding the specific class members (i.e. uses reflection all the way), then you could just pass the result objects around as object types, and not worry about the wrapper at all.
I'm trying to do some unit testing on a project that unfortunately has high level of unit interdependence. Currently, a lot of our classes look to a custom UserIdentity object to determine authentication, but that object has a lot of internal hoop-jumping that I would just as soon avoid when trying to test individual unit functionality.
To work around some of this, I'm trying to create a "mock" version of this UserIdentity that can be plugged in with a more tightly-controlled variable environment.
Long story short, we have a UserIdentity class with several public read-only properties and a static CurrentIdentity (IIdentity) placeholder. I'm able work around just about everything with a "mock" IIdentity implementation, but I'm running into a wall when I reach a point where the CurrentIdentity is cast as a UserIdentity.
It's a pretty straight-forward method:
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = ApplicationContext.User.Identity as UserIdentity;
return currentIdentity;
}
I've set up my mock object to create a member of the UserIdentity type, and then do something like this:
public static implicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
or this
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
The problem is that as far as I can tell, that 'as' doesn't seem to invoke either an implicit or explicit conversion operation on my mock object. My question(s) is(are?), am I missing something simple here or will this not work because (I'm guessing) the 'as' operation looks directly to class inheritance (which my object does not do...)?
Also, a bit off topic maybe, but why can there not be simultaneous explicit and implicit operators of the same resultant type within a class? Unless I'm missing something silly, the compiler balks if I try to have both conversion operators at once. I have to pick one or the other.
UPDATE
Okay, now I'm thoroughly confused. Maybe I'm getting sloppy, but I've tried doing the direct cast, and I can't seem to get that to work either. I read up on the operator at MSDN, and the example shows the operator going in the resultant class rather than the source class, but I'm not sure if that matters or not (I tried both places in the code below). Either way, I tried to set up a simple test bed to see what I might be doing wrong, but I can't get that to work either...Here's what I've got
class Program
{
// Shared Interface
public interface IIdentity { }
// "real" class (not conducive to inheritence)
public class CoreIdentity : IIdentity
{
internal CoreIdentity() { }
// Just in case (if this has to be here, that seems unfortunate)
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// "mock" class (Wraps core object)
public class ExtendedIdentity : IIdentity
{
public CoreIdentity Identity { get; set; }
public ExtendedIdentity()
{
Identity = new CoreIdentity();
}
// This is where the operator seems like it should belong...
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// Dummy class to obtain "current core identity"
public class Foo
{
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
}
static void Main(string[] args)
{
ExtendedIdentity identity = new ExtendedIdentity();
Foo foo = new Foo();
foo.Identity = identity;
CoreIdentity core = foo.GetCoreIdentity();
}
}
But that throws the following exception when I invoke foo.GetCoreIdentity():
Unable to cast object of type 'ExtendedIdentity' to type 'CoreIdentity'.
and I can't catch either of my explicit operators with a break point, so it looks like it's making this determination without even "trying" the conversion routes I've provided.
Surely I'm missing something obvious. Does the fact that I have my Identity (in Foo) defined as IIdentity somehow prevent resolution of the cast using the explicit operators of the implementing type? That would strike me as odd.
UPDATE (#2)
I feel like I'm spamming my post with all these updates (maybe I should get my act together before being so trigger-happy :) ) Anyway, I modified my Foo's GetCoreIdentityMethod to do this instead:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
return (CoreIdentity)exId;
return (CoreIdentity)Identity;
}
and (after having to clean up the ambiguous reference caused by having the operator in both classes), it did step into my explicit conversion operator code, and it did work as expected. So I guess it looks like the explicit operators are not resolved polymorphically (is that the correct understanding?), and the fact that my property was typed as an IIdentity rather than an ExtendedIdentity prevented it from invoking the cast logic even though it was of the ExtendedIdentity type at the time it was invoked. That strikes me as very peculiar and unexpected....and kind of unfortunate.
I don't want to have to re-write the keeper of the CurrentIdentity object to make it aware of my special test cast mocks. I wanted to encapsulate that "special" logic into the mock itself, so this really throws me for a loop.
Does the fact that I have my Identity
(in Foo) defined as IIdentity somehow
prevent resolution of the cast using
the explicit operators of the
implementing type?
Here's a hint: how do you define an explicit (or implicit, for that matter) conversion operator? (I know you know this since you already did it; I am asking the question to illustrate a point.)
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
There's something very important to realize here. The C# designers made the wise choice of making all operators static. So the explicit operator defined above translates to essentially a static method call looking something like this:
public static UserIdentity op_Explicit(MockUserIdentity src)
{
return src.UserIdentity;
}
Now, here is what I'm getting at. The behavior that perplexed you in your question because it seemed to fail in the polymorphism department was really the result of C#'s system of method overload resolution.
If I have two methods:
void Write(string s) { Console.WriteLine("string"); }
void Write(object o) { Console.WriteLine("object"); }
...and then I have this program:
object x = "Hello!";
Write(x);
What will the output be?
The answer is "object" because the Write(object) overload was selected by the compiler -- as well it should have been. Write is not an instance method to be overridden by some derived type according to normal polymorphism; it is a static method, with overloads between which the compiler must make a choice. Since x in the above code is declared to be of type object, that choice is unambiguously Write(object).
So in the case of your code, where you have this:
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
The compiler must investigate: is there an op_Explicit overload which accepts an IIdentity parameter? No, there is not. There's one that accepts a UserIdentity parameter, but that's too specific (just as Write(string) was too specific for x in the example above).
So the reason your explicit operator was not called in your initial tests was that the compiler will not resolve (CoreIdentity)Identity to that particular overload. This is also why your modified version does work:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
{
// Since exId is actually declared to be of type ExtendedIdentity,
// the compiler can choose the operator overload accepting
// an ExtendedIdentity parameter -- so this will work.
return (CoreIdentity)exId;
}
return (CoreIdentity)Identity;
}
as does not invoke conversion operators. See: http://msdn.microsoft.com/en-us/library/cscsdfbt(v=VS.100).aspx
Use a (cast).
So, why don't you use an explicit cast?
// will throw if cast fails
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = (UserIdentity) ApplicationContext.User.Identity ;
return currentIdentity;
}
This ought to trigger your explicit operator. You can test with is first to make it safer.
As mentioned by Ray as doesn't invoke the conversion operators.
That said, you should be using an explicit cast in that type of scenarios.
That way, You get very clear information when something isn't set up right and the object at ApplicationContext.User.Identity wasn't what the code expected it to.
So I have the following simple wrapper class:
interface IReference<out T> where T : myAbstractBase {
T Value { get; }
}
public class Reference<T> : IReference<T> where T : myAbstractBase
{
private T _value = null;
public T Value { get { return _value; } }
}
Throughout my application, I want to have collections of these IReference<someClass> objects (where someClass implements myAbstractBase)
private List<Reference<shapes>> shapeList = new Collection<Reference<shapes>>();
But I want to be able to add all kinds of different shapes to this collection. (Especially since shape is also abstract). Of course, this yields an error:
shapeList.Add( new Reference<circle>(){ radius = 2; } );
The value "Reference[circle]" is not of type "Reference[shape]" and cannot be used in this generic collection.
Is there any way I can design my Reference<T> class such that so long as A is of type B, Reference<A> will be considered of type Reference<B>?
Seems to me like people would run into the same sort of problem trying to use lists of Nullable, etc.
I've tried implementing implicit operators for converting between Reference and T, but I haven't thought of any practical use for them...
public class Reference<T> ... {
...
public static implicit operator Reference<T>(T value)
{
return new Reference<T> { _value = value, };
}
public static implicit operator T(Reference<T> value)
{
return value.Value;
}
}
To anyone curious about my intentions, this is all part of an (ill-fated) attempt to implement lazy loading for a set of classes without having to without having to add anything more to those classes.
Your problem is that you can't chain user defined implicit casts. At first glance it seems like you should be able go from Reference<Circle> -> Reference<Shape> via Reference<Circle> -> Circle -> Shape -> Reference<Shape>. However, you'd be using two user defined implicit casts. First you'd go from Reference<Circle> -> Circle via operator T(Reference<T> value). Then you'd go from
Shape -> Reference<Shape> via operator Reference<T>(T value). You can get around this by creating an overload of the Add method by extending List. This will free you to use one of the user defined cast operators explicitly in Reference.Add. Now, you won't have to chain user defined implicit cast operators.
See the spec on user defined implicit casts: http://msdn.microsoft.com/en-us/library/aa691302(v=vs.71).aspx
//You can get around your inability to chain user defined implicit casts
//by creating a ReferenceList<T> that extends List<IReference<T>>
//and overloads the List.Add method
public class ReferenceList<T> : List<IReference<T>> where T : MyAbstractBase
{
//With this overload you can accept a T. Then explicity cast to Reference<T>
//by using operator Reference<T>(T value)
public void Add(T item)
{
base.Add((Reference<T>)item);
}
}
List<Reference<Shape>> shapeList = new List<Reference<Shape>>();
ReferenceList<Shape> shapeList2 = new ReferenceList<Shape>();
List<IReference<Shape>> shapeList3 = new List<IReference<Shape>>();
//Interesting cases that should work with the OP
//Works for obvious reasons
shapeList.Add(new Reference<Shape>());
//Works because you're using one user defined implicit cast
//where the cast is operator Reference<T>(T value).
//Shape -> Reference<Shape>
shapeList.Add(new Shape());
//Works because you're using one non user defined implicit cast and one user defined
//implicit cast where the user defined implicit cast is operator Reference<T>(T value)
//Circle -> Shape -> Wrapper<Shape>
shapeList.Add(new Circle());
//Does not work because you need to chain two user defined implicit casts
//where the implicit casts are operator T(Reference<T> value) and operator Reference<T>(T value)
//Reference<Circle> -> Circle -> Shape -> Reference<Shape>
//Theoretically this could work, but the C# specs state that chaining user defined
//implicit casts is not allowed in C# (See link below)
shapeList.Add(new Reference<Circle>());
//This case works for similiar reasons that shapeList.Add(new Circle()). It uses
//only one user defined implicit cast because you're calling operator T(Reference<T> value)
//explicitely
shapeList.Add(new (Circle)Reference<Circle>());
//Interesting cases for ReferenceList
//Works because this calls List.Add which accepts a Reference<T>
shapeList2.Add(new Reference<Shape>());
//Works because this calls ReferenceList.Add wich accepts a T
shapeList2.Add(new Circle());
//Works because this calls ReferenceList.Add wich accepts a T.
//and Reference<Circle> can be implicitly cast to a Circle via
//operator T(Reference<T> value).
//Reference<Circle> -> Circle -> Shape -> Reference<Shape> where
//the last cast is done explicitely in the ReferenceList.Add method
//via operator Reference<T>(T value)
shapeList2.Add(new Reference<Circle>());
//Interesting cases for List<IReference<Shape>>
//Works for obvious reasons
shapeList3.Add(new Reference<Shape>());
//Works because IReference is covariant. In C# interfaces can be
//covariant. Classes cannot be covariant.
shapeList3.Add(new Reference<Circle>());
//Does not work because C# does not support user defined implicit
//casts to interface. In other words, you implicitly cast Shape -> Reference<Shape>
shapeList3.Add(new Shape());
//Doesn't work for similiar reasons to why shapeList3.Add(new Shape()) doesn't work
shapeList3.Add(new Circle());
Okay, here's a shot in the dark that should at least make your implicit operator compile. I don't have anything setup that I can test it with right off hand. Still, it should work. Add this to the Reference class.
public static implicit operator Reference<myAbstractBase>(Reference<T> i)
{
return i;
}
Note there's a lack of type checking going on here, so if T isn't derived from myAbstractBase you could be hosed.
I've started down the path of defining a custom collection that is exactly a List<Reference<T>> inside, but it seems to be doing the trick:
public class ReferenceCollection<T> : ICollection<T> where T : myAbstractBase
{
private List<Reference<T>> collection = new List<Reference<T>>();
public IEnumerable<T> toIEnumerable()
{
return (IEnumerable<T>) collection.Select(r => r.Value);
}
public IEnumerator<T> GetEnumerator()
{
return toIEnumerable().GetEnumerator(); ;
}
#region ICollection<T> Members
public void Add(T item)
{
collection.Add(item);
}
...
}
Now I can make the folling call (which I couldn't do before):
ReferenceCollection<shape> test = new ReferenceCollection<shape>();
test.Add(new circle());
Why is it working this way but not the other? Am I really doing anything all that different? Perhaps the conversion is actually now happening in the opposite order (circle gets cast to shape, and then shape gets implicitly converted to Resource<shape> as it's added to the internal collection.)
I can't see any downfalls to this method yet. I could even define implicit converters to turn a ReferenceCollection<T> directly into a List<T> or List<Reference<T>> without so much as iterating over it. Still, I wonder if there's a way to define the original class such that the cast is similarly happening before the implicit conversion to avoid the un-castable wrapped type.
I rephrased the question and got an answer in another thread: How to cast a Generic<T> to a Generic<R> where T is a subclass of R?
The trick was to create a covariant interface IReference<out T> and always use the interface wherever the type is used. So declaring List<IReference<myAbstractBase>> rather than List<Reference<myAbstractBase>>. Details as to why this works at Covariance and Contravariance in Generics
How can you create a default - non indexer - property in C#?
What I mean by this is I can see that I can create indexer default properties as illustrated on this MSDN page.
This allows me to do things like
Widgets widgets = new Widgets();
Widget result = widgets[1];
But what if I want to achieve something like what Nullable<T> does?
Where you can take
Nullable<decimal> nullDec = 1.23m;
decimal result = nullDec.Value;
OR
decimal result = (decimal)nullDec;
Which I assume is simply a default property implementation to nullDec.Value???
Nullable<T> has special handling in the compiler, but you can do most of that by adding implicit or explicit static conversion operators.
For example, for type Foo you can add an operator:
public static implicit operator string(Foo value)
{
return "abc";
}
public static implicit operator Foo(int value)
{
...
}
allowing:
Foo foo = ..
string s = foo; // uses string(Foo value)
and
int i = 123;
Foo foo = i; // uses Foo(int value)
If you inspect the code of Nullable{T} you will see that the explicit cast implementation is like this:
public static explicit operator T(Nullable<T> value)
{
return &value.Value;
}
So yes you are right.
The way Nullable<T> does it is by providing an explicit conversion operator to T.
So perhaps you are looking for something like:
public static explicit operator Widget(Widgets widgets)
{
// Argument checks here.
return widgets[0];
}
which would let you do:
Widgets widgets = ..
Widget firstWidget = (Widget)widgets;
This does look like a really dodgy and unintuitive API to me so I don't recommend doing this at all. Why not just stick to standard indexers?
Not very sure if I correct understant what you're asking for. Wouldn't be enough to implement cast operators on returning type to achieve what you want?
If it's not what you intend, please explain.
Such kind of features are compiler syntactic sugar (in IL code they all are converted to same low level code), so basically it won't be possible to do this without modifying the C# compiler source.