interface IFolderOrItem where TFolderOrItem : FolderOrItem {}
abstract class FolderOrItem {}
class Folder : FolderOrItem {}
abstract class It
If I read it correctly... then the problem is that just because Foo : Bar, that does not mean that ISomething...
In some cases, variance in C# 4.0 may be an option. Alternatively, there are sometimes things you can do with generic methods (not sure it will help here, though).
The closest you can do in C# 3.0 (and below) is probably a non-generic base interface:
interface IFolderOrItem {}
interface IFolderOrItem : IFolderOrItem
where TFolderOrItem : FolderOrItem { }
commonly, the base-interface would have, for example, a Type ItemType {get;} to indicate the real type under consideration. Then usage:
IFolderOrItem SelectedItem { get; set; }
...
public void SomeMagicMethod()
{
this.SelectedItem = GetMagicDocument(); // no cast needed
// not **so** bad
}
From the spec, this relates to §25.5.6 (ECMA 334 v4):
25.5.6 Conversions
Constructed types follow the same conversion rules (§13) as do non-generic types. When applying these rules, the base classes and interfaces of constructed types shall be determined as described in §25.5.3.
No special conversions exist between constructed reference types other than those described in §13. In particular, unlike array types, constructed reference types do not permit co-variant conversions (§19.5). This means that a type
Listhas no conversion (either implicit or explicit) toListeven ifBis derived fromA. Likewise, no conversion exists fromListtoList.[Note: The rationale for this is simple: if a conversion to
Listis permitted, then apparently, one can store values of typeAinto the list. However, this would break the invariant that every object in a list of typeListis always a value of typeB, or else unexpected failures can occur when assigning into collection classes. end note]
The same applies to interfaces. This changes a bit in C# 4.0, but only in some cases.