I'm trying to create an implicit cast that will allow me to use a LINQ result to directly return MyCollection.
public class MyCollection : ICollection<MyType>
{
private List<MyType> _list = new List<MyType>();
public MyCollection(IEnumerable<MyType> collection)
{
_list = new List<MyType>(collection);
}
public static implicit operator MyCollection(IEnumerable<MyType> collection)
{
return new MyCollection(collection);
}
// collection methods excluded for brevity
public MyCollection Filter(string filter)
{
return _list.Where(obj => obj.Filter.Equals(filter)); // cannot implicitly convert
}
}
I've not tried using implicit user-defined casting before, what am I doing wrong?
You aren't allowed to use implicit when either the type cast from, or the type cast to is an interface type. (You also aren't allowed them if one type is derived from the other, which as such bars object as ever being allowed). Indeed, you aren't allowed explicit in this case either. From section ยง17.9.3 of ECMA-364:
A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true, where S0 and T0
are the types that result from removing the trailing ? modifiers, if any, from S and T:
S0 and T0 are different types.
Either S0 or T0 is the class or struct type in which the operator declaration takes place.
Neither S0 nor T0 is an interface-type.
Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.
You are breaking both the third rule (interface type) and the fourth (because there's a non-user-defined conversion from MyCollection to IEnumerable<MyType> already).
If it were allowed, I'd recommend against it anyway.
Implicit casts should only be used when the effect is utterly obvious (to someone with a reasonable knowledge of the language): It's utterly obvious what long x = 3 + 5 does in casting int to long, and utterly obvious what object x = "abc" does in casting string to object.
Unless your use of implicit is of a similar level of "obvious", then it is a bad idea.
In particular, generally implicit casts should not be implicit in the opposite direction, but rather they should be implicit in one direction (the "widening" direction in most built-in cases) and explicit in the opposite direction (the "narrowing" direction). Since you've already got an implicit cast available from MyCollection to IEnumerable<MyCollection>, having an implicit cast available in the opposite direction is pretty much a bad idea.
More generally, since you are talking about use of Linq, there's an even stronger benefit in using an extensible ToMyCollection() method, because then you are going to be following the Linq convention of ToArray(), ToList(), etc.:
public static class MyCollectionExtensions
{
public static MyCollection ToMyCollection(this IEnumerable<MyType> collection)
{
return collection as MyCollection ?? new MyCollection(collection);
}
}
Note that I test for the case where the collection is already MyCollection to avoid wasteful repeated constructions. You may or may not also want to handle the case of List<MyType> specially in using an internal constructor that assigned it to _list directly.
However, you need to consider the aliasing effects that would allow before doing so. This can be a very useful trick if you know aliasing can't cause problems (either the class is only used internally and the aliasing known not to be an issue, or aliasing doesn't hurt the use of MyCollection, or the aliasing is actually desirable). If in doubt, then just have the method do return new MyCollection(collection) to be safer.
You could use custom extension method instead of implicit conversion:
public static class Extension
{
public static MyCollection ToMyCollection(this IEnumerable<MyType> enumerable)
{
return new MyCollection(enumerable);
}
}
And then use it same as ToList :
return _list.Where(obj => obj.Filter.Equals(filter)).ToMyCollection();
This is the actual line which won't work:
public static implicit operator MyCollection(IEnumerable<MyType> collection)
because what you are trying to do is not allowed:
error CS0552: user-defined conversions to or from an interface are not allowed
You can break too much of CLR internals if redefine interface to class casts, so you are not allowed to.
Best way to proceed is to use custom extension method like #Euphoric advices.
In case you want to extend some functionality of IEnumerable, you can easily use an extenstion:
public static class Extensions
{
public IEnumerable<MyType> Filter(this IEnumerable<MyType> e, string filter)
{
return e.Where(T => T.Filter.Equals(filter));
}
}
That will make it work even without casting operators.
In case you want your implicit casting, this tells you that's not that easy.
Why do you need an ICollection? I would use IEnumerable as in the code below. If you need an ICollection instead, just replace IEnumerable below with ICollection, but be consistent and use one or the other, not a mix of both.
public class MyCollection : IEnumerable<MyType>
{
private IEnumerable<MyType> _list;
public MyCollection(IEnumerable<MyType> collection)
{
_list = collection;
}
// collection methods excluded for brevity
public MyCollection Filter(string filter)
{
return new MyCollection(_list.Where(obj => obj.Filter.Equals(filter)));
}
Please note: if you use ICollection instead of IEnumerable, the Filter command should be:
return new MyCollection(_list.Where(obj => obj.Filter.Equals(filter)).ToList());
Related
I have an own class and I need to use a bunch of other classes that I cannot modify. I have written implicit conversions from my own type to the other types:
public class MyClass
{
public static implicit operator YourClass(MyClass m) => new YourClass();
public static implicit operator HisClass(MyClass m) => new HisClass();
}
(In reality all classes have members, but I omit them here in favour of brevity.)
Now I can do this:
var mine = new MyClass();
YourClass yours = mine; // implicit conversion takes place
So far, so good.
Now I want to write a conversion method from some generic class (that I cannot modify) instance of MyType to any of the abovementioned other classes, so that I can do this:
var listOfMine = new List<MyClass>();
List<YourClass> listOfYours = Convert<YourClass>(listOfMine);
(In reality the generic class in question is not List.)
I'd love to write it like this:
public static List<T> Convert<T>(List<MyClass> listOfMine)
where T : MyClass_has_implicit_conversion_to
{
List<T> listOfT = new List<T>();
foreach (var mine in listOfMine)
listOfT.Add(mine); // implicit conversion takes place
return listOfT;
}
, i.e. tell the compiler: T can be any class for which there is an implicit conversion from MyClass to T.
But since such a type constraint does not exist, I cannot tell the compiler that a conversion from MyClass to T is legal. So it complains:
compiler error CS1503: Argument 'mine' cannot convert from MyClass to T.
So what do I do?
I know I can pacify the compiler by doing
listOfT.Add((T)(object)mine);
, but then I get a runtime error - my implicit conversion is never called in that case.
If I need to do the conversion in a different way (i.e. explicit conversion, method like ToYourClass, ..), I can live with that.
But I need the conversion outside of the Convert<T> method, so that I do not need to repeat myself if I create several such Convert<T> methods (e.g. one for List<T>, one for T[], one for Tuple<int,T>, ...).
Charles Mager's comment
Your convert method can't be done as the compiler doesn't know of any relationship between the two types. So you need to specify a function to convert between them.
gave me the following idea:
public static List<T> Convert<T>(List<MyClass> listOfMine, Func<MyClass, T> Convert)
{
List<T> listOfT = new List<T>();
foreach (var mine in listOfMine)
listOfT.Add(Convert(mine)); // manual conversion done here
return listOfT;
}
That's quite alright, I can live with that.
Usage:
var listOfMine = new List<MyClass>();
List<YourClass> listOfYours = Convert<YourClass>(listOfMine, x => x);
x => (YourClass)x would be more explicit but not necessary since I have an implicit conversion defined. I could also define and use any Func<MyClass, YourClass> / Func<MyClass, HisClass> instead of implicit or explicit conversions.
Casting mine to dynamic is a nice idea as well (thanks Charlieface), but it's a source of errors due to missing compiler checks, so I'd like to avoid it if there are other ways.
Java 7 now has this "diamond syntax" where I can do things like ArrayList<int> = new ArrayList<>();
I'm wondering if C# has a similar syntax that I can take advantage of.
For example, I have this part of a class:
class MyClass
{
public List<double[][]> Prototypes; // each prototype is a array of array of doubles
public MyClass()
{
Prototypes = new List<double[][]>; // I'd rather do List<>, in case I change the representation of a prototype later
}
}
Does anyone know if this is possible, and if so, how I might go about using it?
No, there's nothing quite like the diamond syntax in C#. The closest you could come would be to have something like this:
public static class Lists
{
public static List<T> NewList<T>(List<T> ignored)
{
return new List<T>();
}
}
Then:
public MyClass()
{
ProtoTypes = Lists.NewList(ProtoTypes);
}
That just uses normal generic type inference for methods to get T. Note that the value of the parameter is completely ignored - it's only the compile-time type which is important.
Personally I think this is pretty ugly, and I'd just use the constructor directly. If you change the type of ProtoTypes the compiler will spot the difference, and it won't take long at all to fix it up...
EDIT: Two alternatives to consider:
A similar method, but with an out parameter:
public static class Lists
{
public static void NewList<T>(out List<T> list)
{
list = new List<T>();
}
}
...
Lists.NewList(out ProtoTypes);
The same method, but as an extension method, with the name New:
public static class Lists
{
public static List<T> New<T>(this List<T> list)
{
return new List<T>();
}
}
...
ProtoTypes = ProtoTypes.New();
I prefer the first approach to either of these :)
As Jon Skeet said and Eric Lippert backed up, constructors for generic classes in C# cannot infer their types from their parameters or the type of the variable to which the construction is assigned. The go-to pattern when this type of behavior is useful is usually a static generic factory method, which can infer its own generic type from those of its parameters. Tuple.Create() is an example; give it any list of parameters up to 8, and it will create a strongly-typed generic Tuple with those parameters as the data fields. This doesn't work out well for your case, however.
When the variable will be local, consider doing it the other way around; use variable type inference, via the var keyword:
var Prototypes = new List<double[][]>();
This is how the C# team decided to cut down on typing when instantiating variables. Locals are created - and change - much more often than instance variables, and this approach makes C# code look a little more like JavaScript.
As Jon showed, it's possible to hide the mess, but you'll create more of a mess in the process. Here's another possibility using .NET 3.5/4.0's Expression features:
public static string GetName(this Expression<Func<object>> expr)
{
if (expr.Body.NodeType == ExpressionType.MemberAccess)
return ((MemberExpression) expr.Body).Member.Name;
//most value type lambdas will need this because creating the Expression
//from the lambda adds a conversion step.
if (expr.Body.NodeType == ExpressionType.Convert
&& ((UnaryExpression)expr.Body).Operand.NodeType
== ExpressionType.MemberAccess)
return ((MemberExpression)((UnaryExpression)expr.Body).Operand)
.Member.Name;
throw new ArgumentException(
"Argument 'expr' must be of the form ()=>variableName.");
}
public static void InitializeNew(this object me, params Expression<Func<T>>[] exprs)
where T:new()
{
var myType = me.GetType();
foreach(var expr in exprs)
{
var memberName = expr.GetName()
var myMember = myType.GetMember(memberName,
BindingFlags.Instance|BindingFlags.Public
|BindingFlags.NonPublic|BindingFlags.FlattenHierarchy,
MemberTypes.Field|MemberTypes.Property);
if(myMember == null)
throw new InvalidOperationException(
"Only property or field members are valid as expression parameters");
//it'd be nice to put these under some umbrella of "DataMembers",
//abstracting the GetValue/SetValue methods
if(myMember.MemberType == MemberTypes.Field)
((FieldInfo)myMember).SetValue(me, new T());
else
((PropertyInfo)myMember).SetValue(me, new T());
}
}
//usage
class MyClass
{
public List<double[][]> list1;
public List<double[][]> list2;
public MyOtherObject object1;
public MyClass()
{
this.Initialize(()=>list1, ()=>list2);
this.Initialize(()=>object1); //each call can only have parameters of one type
}
}
The implication is obvious here; it's more trouble than it's worth.
To explain why I seemingly just had this laying around; the above is an adaptation of a method I use to throw ArgumentNullExceptions based on passed parameters, which requires the values to be encapsulated within Expressions in order to retain the names of the actual parameters from the calling method. In that situation, the complexity behind the scenes is reduced since all I need in the main helper is a check for null, and the added complexity saves me a lot more than I spend, by allowing me to one-line my null checks in every method and constructor of the codebase.
I recommend ReSharper as a long-term solution to reducing this typing. When the type of an assignment target is known (as it is for instance fields and properties), and you type = new, ReSharper will pop up a suggestion for the type of the constructor, and auto-fill it for you if you want. If you change either the type or constructor afterward, R# will flag the assignment as inconsistent, and you can tell R# to change whichever one you want to match the other.
If you just want to reduce code verbosity there is an opposite shortand syntax: the var operator
Old: List<int> intList = new List<int>();
New: var intList = new List<int>();
At least you write List only once
I have some code like this:
public class EffectValues : IEnumerable<object>
{
public object [ ] Values { get; set; }
public IEnumerator<object> GetEnumerator ( )
{
return this.Values.GetEnumerator ( );
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ( )
{
return this.GetEnumerator ( );
}
}
But the compiler complains saying:
"Cannot implicitly convert type
'System.Collections.IEnumerator' to
'System.Collections.Generic.IEnumerator'.
An explicit conversion exists (are you
missing a cast?)"
I thought the Array type implemented both IEnumerable interfaces, does it not? Because I can use Linq features on the Values instance directly.
This is a subtle and a bit unfortunate. The easy workaround is:
public IEnumerator<object> GetEnumerator ( )
{
return ((IEnumerable<object>)this.Values).GetEnumerator ( );
}
I thought the Array type implemented both IEnumerable interfaces, does it not?
The rules are:
System.Array implements IEnumerable "implicitly", with public methods.
every array type T[] inherits from System.Array.
every array type T[] implements IList<T>, IEnumerable<T> and so on.
therefore every array type T[] is convertible to IEnumerable<T>
Notice that the third point was NOT
every array type T[] implements IList<T>, IEnumerable<T> and so on with public methods and properties defined on T[] that implicitly implement the members
And there you go. When you look up GetEnumerator, we look it up on object[] and don't find it, because object[] implements IEnumerable<object> explicitly. It is convertible to IEnumerable<object>, and convertibility doesn't count for lookups. (You wouldn't expect a method of "double" to appear on int just because int is convertible to double.) We then look at the base type, and find that System.Array implements IEnumerable with a public method, so we've found our GetEnumerator.
That is, think about it like this:
namespace System
{
abstract class Array : IEnumerable
{
public IEnumerator GetEnumerator() { ... }
...
}
}
class object[] : System.Array, IList<object>, IEnumerable<object>
{
IEnumerator<object> IEnumerable<object>.GetEnumerator() { ... }
int IList<object>.Count { get { ... } }
...
}
When you call GetEnumerator on object[], we don't see the implementation that is an explicit interface implementation, so we go to the base class, which does have one visible.
How do all the object[], int[], string[], SomeType[] classes get generated "on the fly"?
Magic!
This is not generics, right?
Right. Arrays are very special types and they are baked in at a deep level into the CLR type system. Though they are very similar to generics in a lot of ways.
It seems like this class object [] : System.Array is something that can't be implemented by a user, right?
Right, that was just to illustrate how to think about it.
Which one do you think is better: Casting the GetEnumerator() to IEnumerable<object>, or just use foreach and yield?
The question is ill-formed. You don't cast the GetEnumerator to IEnumerable<object>. You either cast the array to IEnumerable<object> or you cast the GetEnumerator to IEnumerator<object>.
I would probably cast Values to IEnumerable<object> and call GetEnumerator on it.
I will probably use casting but I am wondering if this is a place where you or some programmer who could read the code, would think it's less clear.
I think it's pretty clear with the cast.
when you said implicit implementation, you mean in the form of Interface.Method, right?
No, the opposite:
interface IFoo { void One(); void Two(); }
class C : IFoo
{
public void One() {} // implicitly implements IFoo.One
void IFoo.Two() {} // explicitly implements IFoo.Two
}
The first declaration silently implements the method. The second is explicit about what interface method it implements.
What's the reason for implementing IEnumerable<T> like that, instead of implicit implementation with public methods? I got curious because you said "This is a subtle and a bit unfortunate", so it seems like it's because of an older decision that forced you to do this I imagine?
I don't know who made this decision. It is kind of unfortunate though. It's confused at least one user -- you -- and it confused me for a few minutes there too!
I would have thought the Array type would be something like this: public class Array<T> : IEnumerable<T> etc. But instead there is some magical code about it then, right?
Right. As you noted in your question yesterday, things would have been a lot different if we'd had generics in CLR v1.
Arrays are essentially a generic collection type. Because they were created in a type system that did not have generics, there has to be lots of special code in the type system to handle them.
Next time you design a type system put generics in v1 and make sure you get strong collection types, nullable types and non-nullable types baked in to the framework from the beginning. Adding generics and nullable value types post hoc was difficult.
You have to cast the array to IEnumerable<object> to be able to access the generic enumerator:
public IEnumerator<object> GetEnumerator() {
return ((IEnumerable<object>)this.Values).GetEnumerator();
}
I want to declare a dictionary that stores typed IEnumerable's of a specific type, with that exact type as key, like so: (Edited to follow johny g's comment)
private IDictionary<Type, IEnumerable<T>> _dataOfType where T: BaseClass; //does not compile!
The concrete classes I want to store, all derive from BaseClass, therefore the idea to use it as constraint. The compiler complains that it expects a semicolon after the member name.
If it would work, I would expect this would make the later retrieval from the dictionary simple like:
IEnumerable<ConcreteData> concreteData;
_sitesOfType.TryGetValue(typeof(ConcreteType), out concreteData);
How to define such a dictionary?
Use System.ComponentModel.Design.ServiceContainer that is already available in .Net framework.
ServiceContainer container = new ServiceContainer();
IList<int> integers = new List<int>();
IList<string> strings = new List<string>();
IList<double> doubles = new List<double>();
container.AddService(typeof(IEnumerable<int>), integers);
container.AddService(typeof(IEnumerable<string>), strings);
container.AddService(typeof(IEnumerable<double>), doubles);
You may not even need a dictionary to be able to do this - but that depends on your needs. If you only ever need 1 such list per type per appdomain (i.e. the "dictionary" is static), the following pattern can be efficient and promotes type-inference nicely:
interface IBase {}
static class Container {
static class PerType<T> where T : IBase {
public static IEnumerable<T> list;
}
public static IEnumerable<T> Get<T>() where T : IBase
=> PerType<T>.list;
public static void Set<T>(IEnumerable<T> newlist) where T : IBase
=> PerType<T>.list = newlist;
public static IEnumerable<T> GetByExample<T>(T ignoredExample) where T : IBase
=> Get<T>();
}
Note that you should think carefully before adopting this approach about the distinction between compile-time type and run-time type. This method will happily let you store a runtime-typed IEnumerable<SomeType> variable both under SomeType and -if you cast it- under any of SomeType's base types, including IBase, with neither a runtime nor compiletype error - which might be a feature, or a bug waiting to happen, so you may want an if to check that.
Additionally, this approach ignores threading; so if you want to access this data-structure from multiple threads, you probably want to add some locking. Reference read/writes are atomic, so you're not going to get corruption if you fail to lock, but stale data and race conditions are certainly possible.
You don't constrain T in the private member; you constrain it at the class level.
class Foo<T> where T : BaseClass
{
private IDictionary<T, IEnumerable<T>> _dataOfType;
public Foo(IDictionary<T, IEnumerable<T>> dataOfType)
{
this._dataOfType = dataOfType;
}
}
You can't constrain a specific variable. It only works on classes and methods. It really doesn't make any sense in the variable level, to be honest.
What you want is a custom class - class WeirdDictionary : IDictionary<Type, IEnumerable>, that will overload the Add method to take a Type and an IEnumerable of that type, which you can do using constraints, and cast the IEnumerable<> to IEnumerable. Overload the indexer aswell, and cast it back to the relevant type.
All this casting is needed, since generics are strict about IEnumerable<Base> being as good as IEnumerable<Derived> (This is called variance, I believe?)
This solution is slightly generalized, since reuse rocks
Edit by 280Z28:
At first I marked this down because point #2 was confusing and I misinterpreted it. By using explicit implementation of methods in IDictionary<Type, IEnumerable> and providing generic alternatives, you can get a pretty clean interface. Note that you cannot create generic indexers, so you'll have to always use TryGet<T> (which is a good idea anyway). I only included explicit implementation of one of the IDictionary<> methods to show how to perform the checks. Do not derive WeirdDictionary directly from Dictionary<Type, IEnumerable> or you will lose the ability to guarantee constraints in the underlying data.
class WeirdDictionary : IDictionary<Type, IEnumerable>
{
private readonly Dictionary<Type, IEnumerable> _data =
new Dictionary<Type, IEnumerable>();
public void Add<T>(IEnumerable<T> value)
{
_data.Add(typeof(T), value);
}
public bool TryGet<T>(out IEnumerable<T> value)
{
IEnumerable enumerable;
if (_data.TryGetValue(typeof(T), out enumerable)
{
value = (IEnumerable<T>)enumerable;
return true;
}
value = null;
return false;
}
// use explicit implementation to discourage use of this method since
// the manual type checking is much slower that the generic version above
void IDictionary<Type, IEnumerable>.Add(Type key, IEnumerable value)
{
if (key == null)
throw new ArgumentNullException("key");
if (value != null && !typeof(IEnumerable<>).MakeGenericType(key).IsAssignableFrom(value.GetType()))
throw new ArgumentException(string.Format("'value' does not implement IEnumerable<{0}>", key));
_data.Add(key, value);
}
}
End 280Z28
Make a custom Dictionary class:
public class BaseClassDictionary<T, IEnumerable<T>> : Dictionary<T, IEnumerable<T>>
where T : BaseClass
{
}
Then you can use this specialized dictionary instead as field type:
private BaseClassDictionary<BaseClassDerivedType, IEnumerable<BaseClassDerivedType>> myDictionary;
Try this:
public class MyCustomDictionary<T>: Dictionary<T, IEnumerable<T>> { }
I have a generic class that I'm trying to implement implicit type casting for. While it mostly works, it won't work for interface casting. Upon further investigation, I found that there is a compiler error: "User-defined conversion from interface" that applies. While I understand that this should be enforced in some cases, what I'm trying to do does seem like a legitimate case.
Here's an example:
public class Foo<T> where T : IBar
{
private readonly T instance;
public Foo(T instance)
{
this.instance = instance;
}
public T Instance
{
get { return instance; }
}
public static implicit operator Foo<T>(T instance)
{
return new Foo<T>(instance);
}
}
Code to use it:
var concreteReferenceToBar = new ConcreteBar();
IBar intefaceReferenceToBar = concreteReferenceToBar;
Foo<ConcreteBar> concreteFooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromInterfaceBar = intefaceReferenceToBar; // doesn't work
Does anyone know a workaround, or can anyone explain in a satisfactory way why I shuouldn't be able to cast interfaceReferenceToBar implicitly to Foo<IBar>, since in my case it is not being converted, but only contained within Foo?
EDIT:
It looks like covariance might offer salvation. Let's hope the C# 4.0 specification allows for implicit casting of interface types using covariance.
The reason you can't do this is because it is specifically forbidden in the C# language specification:
Source: ECMA-334 Section 15.10.4
A class or struct is permitted to
declare a conversion from a source
type S to a target type T provided all
of the following are true:
...
Neither S nor T is object or an interface-type.
and
User-defined conversions are not
allowed to convert from or to
interface-types. In particular, this
restriction ensures that no
user-defined transformations occur
when converting to an interface-type,
and that a conversion to an
interface-type succeeds only if the
object being converted actually
implements the specified
interface-type.