Imagine I have several classes of different types with the same property.
I want to make a generic method that should acess the value of the property of those classes.
The following code is invalid and will throw this error :
Cannot resolve method 'GetValue(T)' (...)
.. so what's the proper way to do this?
public static List<int> FooBar<T>(T myObject)
{
var myValue = typeof(T).GetProperty("myList").GetValue(myObject);
return myValue;
}
The "proper" way to do this is probably to have a where T : SomeInterfaceOrBaseType, i.e. the thing that has a myList member - and then just access it; i.e. return myObject.myList;
interface IFoo {
List<int> myList {get;}
}
public static List<int> FooBar<T>(T myObject) where T : IFoo {
return myObject.myList;
}
But... by the time you've done that, there's not really a need for the method any more, as if the caller knows that the type is an IFoo, they can do that themselves.
If you must do it via reflection... well, that's hard. It might be easier to just abuse dynamic:
public static List<int> FooBar<T>(T myObject)
{
dynamic obj = myObject;
List<int> myList = obj.myList;
return myList;
}
you can do like this myObject.GetType().GetProperty("myList").GetValue(myObject, null);
If you really want to do this with generics, try the code below
return (List<int>)(typeof(T).GetProperty("myList").GetValue(myObject, null))
Related
In JQuery you can write $('.my-class').hide() and it will call hide() on all the results. There's no for loop, no iterating, no LINQ extensions and lambdas etc. and it makes dealing with lists super fun. I want to be able to have this functionality on IEnumerables in C#. I think Matlab has a similarly concise syntax when operating on arrays/matrices.
Long story short, I want the following code (or similar) to work:
class Program
{
static List<MyClass> MyList = new List<MyClass>();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
MyList.Add(new MyClass());
MyList.MyMethod();
// should be exactly equivalent to:
MyList.Select(n => n.MyMethod());
}
}
class MyClass
{
public int MyMethod() { return 123; }
}
I'm aware this is possible on a case-by-case basis using extension methods:
public static IEnumerable<int> MyMethod(this IEnumerable<MyClass> lst)
{
return lst.Select(n => n.MyMethod());
}
But we'd have to create one extension method for every single method on every single type that you wanted this behaviour on.
Ideally this would be possible for all types and all methods and still be type-safe at compile time. I suspect I'm asking too much from the C# language here, but how would we do this or something similar in a as-generic-as-possible way?
Possible solutions:
Auto-generate extension methods for particular types. If we only intend to use this notation for a few types, we could just generate the extension methods once automatically. This would achieve the exact syntax and full type safety but generating code would be a pain.
A single extension method that returns a dynamic object built using reflection on the supplied type. The idea is that we'd use reflection to iterate through the type's methods and build up a dynamic object that would have all the methods like .MyMethod() that would behind the scenes call Select(...) on the IEnumerable. The syntax would end up being something like MyList.Selector().MyMethod(). But now we've lost the syntax and type safety. Clever, maybe. Useful, probably not.
Intercepting method calls? Is it possible to decide how to react to a method call at runtime? I don't know. Again you'd lose type safety.
The most simple solution is using dynamic objects. If you are willing to throw away type safety, you can make a IEnumerable type that behaves statically when needed and dynamically otherwise, here's a sample prototype:
public class DynamicIEnumerable<T> : DynamicObject, IEnumerable<T>
{
public IEnumerable<T> _enumerable;
public DynamicIEnumerable(IEnumerable<T> enumerable)
{
this._enumerable = enumerable;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
result = new DynamicIEnumerable<T>(_enumerable.Select(x => (T)typeof(T).InvokeMember(binder.Name, BindingFlags.InvokeMethod, null, x, null)));
return true;
}
public IEnumerator<T> GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
}
In TryInvokeMember, the invoked member on IENumerable is applied on all items using reflection. The only constraints on this approach is that you have to return this in invoked method. Here's a sample of how to use this approach:
public class SomeClass
{
public int Value {get;set;}
public SomeClass(int value)
{
this.Value = x;
}
public SomeClass Plus10()
{
Value += 10;
return this;
}
}
static void Main()
{
dynamic d = new DynamicIEnumerable<X>(Enumerable.Range(0, 10).Select(x => new SomeClass(x)));
foreach (var res in d.Plus10().Plus10())
Console.WriteLine(res.Value);
}
how would we do this or something similar in a as-generic-as-possible way?
This isn't a pretty solution but it does work:
public class MyClass
{
public void MyMethod()
{
}
public void MyMethod2()
{
}
}
Extension Method:
public static class WeirdExtensions
{
public static IEnumerable<T> CallOnAll<T>(this IEnumerable<T> instance ,
Action<T> call)
{
foreach(var item in instance)
{
call(item);
}
return instance;
}
}
Usage (chaining/fluent):
var blah = new List<MyClass>();
blah.CallOnAll(b => b.MyMethod())
.CallOnAll(b => b.MyMethod2());
Notes
This isn't quite possible due to a the underlying assumption that you'd have to every single method on every single type. In jQuery/Html there is only one underlying type of an Html Element. All elements are exposed to the same methods (whether or not the type supports it). In jQuery, you can call $('head').hide() but it won't do anything visually, but because it is an element, it will be inline styled. If you need a new method, you do have a build one, but for only one type because there is only one type.
In contrast with C# you build your types (many many types) and they all have different methods (sure there could be overlap).
I have a class that implements IComparable. It works but the comparison is static, i.e. it's always the same ordering it achieves. What would be a good method to introduce comparison by a parameter, i.e. if we have:
class Poo : IComparable {
public int A { ... };
public int B { ... };
...
}
IEnumerable<Foo> list = ...;
list = list.Sort(???);
I' d like to order the list with respect to A or B depending on the parameter passed to Sort at the question marks. What's the most efficient way to do that?
At the moment, the best method I've came up with is to declare a couple of methods that I pass to Sort as delegates.
private static int CompareWrtA(Foo foo1, Foo foo2) { ... }
private static int CompareWrtB(Foo foo1, Foo foo2) { ... }
if(withRespectToA)
list = list.Sort(CompareWrtA);
else
list = list.Sort(CompareWrtB);
But it doesn't feel really as the best way. Criticism is welcome.
If you want to simplify that statement you can write it like this:
list.Sort((x,y) => withRespectToA ? CompareWrtA(x,y) : CompareWrtB(x,y));
BTW, Sort method is modifying your list, it doesn't return anything.So you don't need to assign it back to your list.
I was doing some work with interfaces today, when I run into the following scenario. Given these two simple interfaces:
public interface IItem { }
public interface IInventory
{
ICollection<IItem> Items { get; }
}
I made a simple class to implement IInventory, and noticed that this implementation is perfectly fine as written:
public class BasicInventory1 : IInventory
{
private Dictionary<int, IItem> items;
public ICollection<IItem> Items
{
get { return items.Values; }
}
}
But yet, this implementation requires a cast:
public class BasicInventory2 : IInventory
{
private Dictionary<int, IItem> items;
public ICollection<IItem> Items
{
get { return (ICollection<IItem>)items; }
}
}
Why does one require a cast and the other doesn't? Checking the object typing for both collections that are getting returned in either case confirms that they both in fact implement ICollection.
I suspect there is some magic type conversions going on under the hood here, and therefore seems to have something to do with co/contravariance, but I don't quite see what exactly is going on.
Dictionary<int, IItem> does not implement ICollection<IItem>. Simple as that.
It wouldn't make sense to implement that interface because you cannot add to a dictionary without specifying a key. The interface does not make sense.
This is a runtime error because items could refer to a subclass of Dictionary so that the cast might be valid.
I think that if you were to add .Values to the second example, you would not need the cast
public class BasicInventory2 : IInventory
{
private Dictionary<int, IItem> items;
public ICollection<IItem> Items
{
get { return items.Values; }
}
}
This is because items is a Dictionary and that implements ICollection<KeyValuePair<TKey, TValue>>.
This code is NOT VALID and will always generate a runtime error:
public class BasicInventory2 : IInventory
{
private Dictionary<int, IItem> items = new Dictionary<int, IItem>();
public ICollection<IItem> Items
{
get
{
return (ICollection<IItem>) items;
}
}
}
A Dictionary<int, IItem> does NOT implement ICollection<IItem>, whereas the type returned from Dictionary<int, IItem>.Values does.
So the answer is:
The first case is ok because Values is of the correct type.
In the second case, the compiler knows that you are trying to return the wrong type and so it gives you a compile error.
If you override the error with a case, you will get a runtime BadCastException.
In BasicInventory1 you return items.Values in BasicInventory2 you return only items.
.Values returns a ICollection, so no cast is need.
MSDN:
Dictonary
Values
In the second code you use the dictionary as return value where in the first code you use the values. Dictionary<int,IItems> inherits from ICollection<KeyValuePair<int,IItems>> thus is not ICollection<IItems>. Therefore you need the cast.
Let's say I have the following classes that have different implementations based on the object to be stored in:
public class ListOfPersistent<T> :
IList<T> where T : Persistent {... implementation ...}
public class ListOfNonPersistent<T> :
IList<T> {... implementation ...}
And I want to use one of another version on the above classes by doing something like this:
public class PersistentList<T> : IList<T> {
protected PersistentList() {
if (list != null) {
return;
}
if (Extensions.IsPersistent<T>()) {
list = new ListOfPersistent<T>();
} else {
list = new ListOfNonPersistent<T>();
}
}
protected IList<T> list;
....
}
Of course the above does not compiles, because there is a type constrain on the first class and none on the second. Is there any way I can: Tell the compiler that it should not check the constrain on this specific case (list = new ListOfPersistent<T>()) because I KNOW it will be of that type, or do some covariance/contravariance magic so the code compiles without any issues?
Covariance and contravariance won’t help you here because IList<T> is invariant.
Personally I would argue that you have a flaw in your class design. You shouldn’t want to instantiate a ListOfPersistent<T> and then place it in a variable whose type, IList<T>, is incompatible. Unfortunately I cannot suggest a good alternative because I have no idea how you are planning to use these classes or what your overall goal is; but I can make a suggestion with a disclaimer that it is hacky and should probably only be used if you really know what you are doing:
public static class ListUtils
{
public static object CreateListOfPersistent(Type elementType)
{
if (!typeof(Persistent).IsAssignableFrom(elementType))
throw new ArgumentException("elementType must derive from Persistent.", "elementType");
var listType = typeof(ListOfPersistent<>).MakeGenericType(elementType);
return Activator.CreateInstance(listType);
}
}
// ...
if (Extensions.IsPersistent<T>())
list = (IList<T>) ListUtils.CreateListOfPersistent(typeof(T));
else
list = new ListOfNonPersistent<T>();
I have class where the relevant part looks like
class C {
void Method<T>(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
How should I define the list so that the class compiles?
I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)
I don't think you can do this in C#... you would have to add the type parameter to the class:
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<SomeClass<T>> list = new List<SomeClass<T>>();
}
The other option would be to use an interface:
class C {
void Method<T>(T obj)
where T : ISomeClass {
list.Add(obj);
}
List<ISomeClass> list = new List<ISomeClass>();
}
To do what you want, you have two options.
You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.
Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.
Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant.
You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature.
To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead.
If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.
I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.
class SomeClass<T>
{
}
class C
{
void Add<T>(SomeClass<T> item)
{
Type type = typeof(SomeClass<T>);
if (!list.ContainsKey(type))
list[type] = new List<SomeClass<T>>();
var l = (List<SomeClass<T>>)list[type];
l.Add(item);
}
public void Method<T>(SomeClass<T> obj)
{
Add(obj);
}
readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
}
test it with the following:
class Program
{
static void Main(string[] args)
{
var c = new C();
var sc1 = new SomeClass<int>();
var sc2 = new SomeClass<String>();
c.Method(sc1);
c.Method(sc2);
c.Method(sc1);
c.Method(sc2);
}
}
Personally, I would do this where possible; move the generic parameter from the method, to the class.
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.