I have a generic extension method like following:
public static class Validator
{
public static IEnumerable<string> Validate<T>(IList<T> items)
{
foreach (var item in items)
{
var result = MyValidator.Validate(item);
if (!result.Any()) continue;
foreach (var validationResult in result)
yield return validationResult.ErrorMessage;
}
}
public static IEnumerable<string> Validate<T>(T item)
{
var result = MyValidator.Validate(item);
if (!result.Any()) yield break;
foreach (var validationResult in result)
yield return validationResult.ErrorMessage;
}
}
But when I call the method for single object or collection it calls Validate(T item);
var item = new Person();
var items = new List<Person>();
var v1 = Validator.Validate(item); // calls Validate<T>(T item)
var v2 = Validator.Validate(items); // calls Validate<T>(T item) but should call Validate<T>(IList<T> items)
I wan to call Validate<T>(IList<T> items) for list.
Why this problem occured?
These extension methods have similar signatures - IList<T> items is T item.
Renaming Validate<T>(IList<T> items) to ValidateList<T>(IList<T> items) or renaming Validate<T>(T item) to ValidateItem<T>(T item) would provide the result you are looking for.
That's because interfaces have lower priority in overloads resolutions than concrete types
As #JonSkeet points out, it may be because the type conversion from T to T is better than List<T> to IList<T>, so the compiler chooses the generic overload.
In your case, you would get the desired behavior by changing the method's parameter from IList<T> to List<T>.
public interface IFoo { }
public class Foo : IFoo { }
public static class Validator
{
public static void Method<T>(T t) { }
public static void Method(object o) { }
public static void Method(IFoo i) { }
}
static void Main()
{
var foo = new Foo();
Validator.Method(foo); // Invokes Method<T>(T t)
object o = foo;
Validator.Method(o); // Explicit object, invokes Method(object o)
IFoo i = foo;
Validator.Method(i); // Explicit interface, invokes Method(IFoo i)
}
Related
I have the following:
public static void ForEachIterationIn(IEnumerable<T> list, Action<T> action)
{
foreach(T item in list)
{
action(item);
}
}
and am able to call it this way:
ForEachIterationIn(list, item => DoSomething(item));
Is it possible to use method chaining to do the following?
ForEachIterationIn(list).Do(item => DoSomething(item));
So that if I decide to, I can extend it and create something like:
ForEachIterationIn(list).RemoveWhen(item => item != 10);
Which means each method would basically do the following:
foreach(T item in list)
{
Do(action(item));
// Or RemoveWhen(action(item))
// Or whatever method I use in the chain
}
You could do something like below:
public class Iterator
{
public List<string> Items { get; set; }
public Iterator(List<string> items)
{
Items = items;
}
public Iterator AddString(string s)
{
this.Items.Add(s);
return this;
}
public Iterator AddAnotherString(string s)
{
this.Items.Add(s);
return this;
}
public override string ToString()
{
return String.Join('-', this.Items.ToArray());
}
}
And then use it:
class Program
{
static void Main(string[] args)
{
var items = new List<string> { "a", "b" };
var iterator = new Iterator(items);
Console.WriteLine(iterator.AddString("c").AddAnotherString("d").ToString());
}
}
var someList = otherList.ReplaceAll(foo, bar);
if (someCondition)
{
someList = someList.ReplaceAll(someOtherFoo, someOtherBar);
}
In my code, I am having the above code snippet, I find the if statement very annoying and would like to do something like this instead:
var someList = otherList
.ReplaceAll(foo, bar)
.Given(someCondition)
.ReplaceAll(someOtherFoo, someOtherBar);
such that ReplaceAll(someOtherFoo, someOtherBar) is only executed when someCondition is true.
Is that possible?
While you can indeed create an extension as suggested by others, I wouldn't do that in actual production code because it's defeats the purpose of Linq.
Linq is functional and good for processing sequences or streams. Each Linq chaining operator processes incoming data and transforms it to another data. Given extension you are looking for is procedural and doesn't do anything with the sequence.
Given also doesn't support lazy evaluation which is one of the features of Linq.
By introducing such extension you just making the code harder to read for the next person working on this code.
By contrast, good old if can be easily understood by everyone.
If you want to save couple of lines you can use ternary operator:
var someList = otherList.ReplaceAll(foo, bar);
someList = someCondition ? someList.ReplaceAll(someOtherFoo, someOtherBar) : someList;
Why don't you create an extension?
public static List<T> ExecuteIf<T>(
this List<T> list,
Func<bool> condition,
Func<List<T>, List<T>> action)
{
return condition() ? action(list) : list;
}
var someList = otherList
.ReplaceAll(foo, bar)
.ExecuteIf(() => someCondition, (l) => l.ReplaceAll(someOtherFoo, someOtherBar));
what you are describing is called a fluent interface
the linq functions are extension functions with a signature like
IEnumerable<T> someFunction<T>(this IEnumerable<T>, ...)
as you see it's an ordinary function that returns something ...
fluent interfaces make use of this by returning something that is implementing an interface for enumeration in this case, but also using the return type to change the set of functions you can call on the result ...
here is an example program...
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace SoFluentExample
{
class Program
{
static void Main(string[] args)
{
var en = Enumerable.Range(0, 10).Concat(Enumerable.Range(0, 10));
var result = en
.ReplaceAll(1, 100)
.Given(true)
.ReplaceAll(2, 200)
.Given(false)
.ReplaceAll(3,300)
.ToArray();
}
}
public class MyFluentEnumerableWithCondition<T> : IEnumerable<T>
{
public IEnumerable<T> en { get; private set; }
public bool condition { get; private set; }
public MyFluentEnumerableWithCondition(IEnumerable<T> en, bool condition)
{
this.en = en;
this.condition = condition;
}
public IEnumerator<T> GetEnumerator()
{
return en.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return en.GetEnumerator();
}
}
public class MyFluentReplacerEnumerable<T> : IEnumerable<T>
{
private IEnumerable<T> en;
private T foo;
private T bar;
public MyFluentReplacerEnumerable(IEnumerable<T> en, T foo, T bar)
{
this.en = en;
this.foo = foo;
this.bar = bar;
}
public IEnumerator<T> GetEnumerator()
{
return new MyEnumerator(en.GetEnumerator(), foo, bar);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private class MyEnumerator : IEnumerator<T>
{
private IEnumerator<T> en;
private T foo;
private T bar;
public MyEnumerator(IEnumerator<T> enumerator,T foo, T bar)
{
this.en = enumerator;
this.foo = foo;
this.bar = bar;
}
public T Current => replace(en.Current,foo,bar);
private T replace(T current, T foo, T bar)
{
return current.Equals(foo) ? bar : current;
}
object IEnumerator.Current => Current;
public bool MoveNext()
{
return en.MoveNext();
}
public void Reset()
{
en.Reset();
}
#region IDisposable Support
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
en.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}
public static class MyExtension
{
public static IEnumerable<T> ReplaceAll<T>(this IEnumerable<T> en,T foo, T bar)
{
return new MyFluentReplacerEnumerable<T>(en, foo, bar);
}
public static MyFluentEnumerableWithCondition<T> ReplaceAll<T>(this MyFluentEnumerableWithCondition<T> en, T foo, T bar)
{
if (!en.condition)
return en;
return new MyFluentEnumerableWithCondition<T>(en.en.ReplaceAll(foo,bar),true);
}
public static MyFluentEnumerableWithCondition<T> Given<T>(this IEnumerable<T> en, bool condition)
{
return new MyFluentEnumerableWithCondition<T>(en, condition);
}
}
}
ReplaceAll is defined for IEnumerable<T> and MyFluentEnumerableWithCondition<T>
the type decides which implementation is called, and even though MyFluentEnumerableWithCondition<T> is implementing IEnumerable<T>, the more specific signature is used
To use fluent method chaining with such a conditional operation, you could create a ReplaceAllIf extension method:
public static class Extensions
{
public static List<T> ReplaceAllIf<T>(this List<T> list, bool condition, T valueToFind, T replacement)
{
return condition ? list.ReplaceAll(valueToFind, replacement) : list;
}
public static List<T> ReplaceAll<T>(this List<T> list, T valueToFind, T replacement)
{
return list.Select(x => x.Equals(valueToFind) ? replacement : x).ToList();
}
}
And then use it like this:
var list = new List<string>{"a", "b", "c", "d", "a", "b", "c", "d"};
var result = list
.ReplaceAll("a", "XXXX")
.ReplaceAllIf(true, "c", "YYYY")
.ReplaceAllIf(false, "d", "ZZZZ");
Working demo -> https://dotnetfiddle.net/gknS4z
How can loop through this list through a foreach loop I get an error saying does not contain a public instance definition for GetEnumerator
public class GenericList<T>
{
public void Add(T use) { }
}
static void Main(string[] args)
{
GenericList<int> list1 = new GenericList<int>();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.Add(4);
list1.Add(5);
foreach(int i in list1)
{
Console.WriteLine(i);
}
So generally just use List, meaning your code should just be:
static void Main(string[] args)
{
var list1 = new List<int>();
list1.Add(1);
list1.Add(2);
list1.Add(3);
list1.Add(4);
list1.Add(5);
foreach(int i in list1)
{
Console.WriteLine(i);
}
However, what I am guessing you are asking is what is required to use foreach on your own type.
The answer is a bit of compiler magic of duck typing. If your iteration class implements a method called GetEnumerator() returning a type complying with certain rules (a MoveNext method taking no parameters and returning a bool and a Current Property you are good to go, see the most useless iterator ever below:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var x= new MyIterable();
foreach (var item in x)
{
Console.WriteLine(item);
}
}
}
public class MyIterable
{
public Item Current { get; set; }
public bool MoveNext()
{
return false;
}
public MyIterable GetEnumerator()
{
return this;
}
}
public class Item
{
}
See https://blogs.msdn.microsoft.com/kcwalina/2007/07/18/duck-notation/
I'm writing an application where I am required to use Reflection to call a method which has parameters of type MyObject.
Method (List<MyObject> input , out List<MyObject> output,..... );
Using reflection I send the parameter of type Object. How can I cast List<MyObject> to List<object>
var parameters = new Object[] { inputs, outputs, userPrams };
System.Type classType = typeof(MyClass);
object instance = Activator.CreateInstance(classType);
classType.InvokeMember(name, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,null, instance, parameters);
In the code above both input and output are lists of type MyObject
I tried to Cast them to List of Objects but this doesn't work
x.Outputs = grOutputs as IList<object>
Can anyone help?
Your question is not 100% clear, so I assumed the problem you're facing is the one you put in the title:
Cast List of MyType to List of objects
As #Charles said, IList<T> and List<T> are not variant, so you can't cast IList<DerivedClass> to IList<BaseClass>. You have to create new List<BaseClass>.
There are many ways to do that, I think there are two you should consider:
You can use Cast and ToList, but it will require using System.Linq.
var listOfStrings = new List<string>() { "foo", "bar" };
var listOfObjects = listOfStrings.Cast<object>().ToList();
To avoid that, you can use new List<T>(IEnumerable<T> source) constructor. Because IEnumerable<T> is covariant, you can do following:
var listOfStrings = new List<string>() { "foo", "bar" };
var listOfObjects = new List<object>(listOfString);
You might well want to do something like this:
var dogs = new List<Dog>();
var pets = (List<object>)dogs;
pets.Add(new Cat());
The C# language is heavily invested in you stop mixing cats and dogs like this. It violates the hard guarantee that the list only ever contains dogs. You'll have to do it like this instead:
var dogs = new List<Dog>();
var pets = new List<object>(dogs);
pets.Add(new Cat());
Which is fine, it creates a new list, one that no longer guarantees that it only ever contains dogs since it only promises that the list contains object. Pretty useless, typically, you basically lose all knowledge of what the list contains. Forcing you to write hunt-the-fox code that uses the as operator or Reflection to find the proper animal back. Code that fails to do its job at run-time instead of the compiler telling you that its wrong code at build time, when you're still in the comfortable cubicle cocoon.
Which it did.
IList<T> is not covariant, you would need to create a new list if you wanted IList<object>:
x.Outputs = grOutputs.Cast<object>().ToList();
If I understand your question, you could try something like this :
var objList = myClassList.OfType<object>();
You cannot make your desired cast because, as others have written, collections in c# are not covariant.
You can either create a new list, or introduce a ListWrapper class like so:
public class ListWrapper<TOut, TIn> : IList<TOut> where TIn : class, TOut where TOut : class
{
readonly IList<TIn> list;
public ListWrapper(IList<TIn> list)
{
if (list == null)
throw new NullReferenceException();
this.list = list;
}
#region IList<TOut> Members
public int IndexOf(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return -1;
return list.IndexOf(itemIn);
}
public void Insert(int index, TOut item)
{
list.Insert(index, (TIn)item);
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public TOut this[int index]
{
get
{
return list[index];
}
set
{
list[index] = (TIn)value;
}
}
#endregion
#region ICollection<TOut> Members
public void Add(TOut item)
{
list.Add((TIn)item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return false;
return list.Contains(itemIn);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (var item in list)
{
array[arrayIndex] = item;
arrayIndex++;
}
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get
{
return list.IsReadOnly;
}
}
public bool Remove(TOut item)
{
return list.Remove(item as TIn);
}
#endregion
#region IEnumerable<TOut> Members
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in list)
yield return item;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
You might want to make the wrapper read-only since the setter could throw an exception if the incoming object is not of the inner list's item type.
So I have an interface called IWorkItem that is implemented in WorkA, WorkB and many other classes.
public interface IWorker<T> where T : IWorkItem
{
void Process(T item);
}
The IWorker<T> interface is implemented in WorkerA (IWorker<WorkA>), WorkerB (IWorker<WorkB>) and many other classes.
public static void ProcessWorkItem(IWorkItem item)
{
(/* find the right worker */).Process(item);
}
Now my problem is: How do find a worker object that is able to process the given IWorkItem?
My first attempts look like this, but the generic type arguments are a problem:
public static class WorkerRepository
{
private static Dictionary<Type, IWorker<???>> RegisteredWorkers =
new Dictionary<Type, IWorker<???>>();
public static void RegisterWorker(IWorker<???> worker)
{
var handled = from iface in worker.GetType().GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() == typeof(IWorker<>)
select iface.GetGenericArguments()[0];
foreach (var type in handled)
if (!RegisteredWorkers.ContainsKey(type))
RegisteredWorkers[type] = worker;
}
public static void ProcessWorkItem(IWorkItem item)
{
RegisteredWorkers[item.getType()].Process(item);
}
}
So I have the Dictionary that contains the workers. Which type argument do I need here? In Java I could just use ? extends IWorkItem, but do I do that in C#?
Then there is RegisterWorker. You would probably suggest a generic type argument for the entire method, like RegisterWorker<T>(IWorker<T> worker). However, that also won't work, since I would like to dynamically load, instantiate and register Workers.
Is this even the right approach or is there a better way to accomplish this?
I made a few changes but got a solution where you can keep things generic (instead of using objects). Not sure if you even care, but thought to add it as answer and let you decide.
I also wrote a test to check if it actually works, you should be able to copy/paste it.
[TestFixture]
public class WorkerThing
{
[Test]
public void RegisterAndRetrieveWorkers()
{
var repo = new WorkerRepository();
repo.RegisterWorker(new WorkerA());
var workerA = repo.RetrieveWorkerForWorkItem(new WorkItemA());
Assert.IsTrue(workerA is WorkerA);
repo.RegisterWorker(new WorkerB());
var workerB = repo.RetrieveWorkerForWorkItem(new WorkItemB());
Assert.IsTrue(workerB is WorkerB);
}
}
The WorkerRepository class.
public class WorkerRepository
{
private readonly Dictionary<Type, IWorker<IWorkItem>> _registeredWorkers =
new Dictionary<Type, IWorker<IWorkItem>>();
public void RegisterWorker(IWorker<IWorkItem> worker)
{
var type = (from iface in worker.GetType().GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() == typeof(IWorker<>)
select iface.GetGenericArguments()[0]).First();
if (!_registeredWorkers.ContainsKey(type))
{
_registeredWorkers[type] = worker;
}
}
// You don't need this method, just added it to check if I indeed retrieved the correct type
//
public IWorker<IWorkItem> RetrieveWorkerForWorkItem(IWorkItem item)
{
var type = item.GetType();
var registeredWorker = _registeredWorkers[type];
return registeredWorker;
}
public void ProcessWorkItem(IWorkItem item)
{
var type = item.GetType();
var registeredWorker = _registeredWorkers[type];
registeredWorker.Process(item);
}
}
The work item interfaces & classes.
public interface IWorkItem
{
}
public class WorkItemA : IWorkItem
{
}
public class WorkItemB : IWorkItem
{
}
And here I added the out keyword to allow covariance typing on the interface. That way you can convert WorkerA to IWorker<IWorkItem>. (as in the unit test example)
public interface IWorker<out T> where T : IWorkItem
{
void Process(IWorkItem workItem);
}
public class WorkerA : IWorker<WorkItemA>
{
public void Process(IWorkItem item)
{
}
}
public class WorkerB : IWorker<WorkItemB>
{
public void Process(IWorkItem item)
{
}
}
No object dictionaries. No reflection. I hope the example is useful!
Cheers (and thx for the cool question, it kept me busy for a while :))
It looks like you want something like this:
private static Dictionary<Type, object> RegisteredWorkers = new Dictionary<Type, object>();
public static void RegisterWorker(object worker)
{
var handled = from iface in worker.GetType().GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() == typeof(Worker<>)
select iface.GetGenericArguments()[0];
foreach (var type in handled)
if (!RegisteredWorkers.ContainsKey(type))
RegisteredWorkers[type] = worker;
}
public static void ProcessWorkItem(WorkItem item)
{
object handler = RegisteredWorkers[item.getType()];
Type workerType = typeof(Worker<>).MakeGenericType(item.GetType());
MethodInfo processMethod = workerType.GetMethod("Process");
processMethod.Invoke(handler, new object[] { item });
}
If you don't want to invoke the handlers through reflection each time you can generate an Action<IWorkItem> handler when you register the handler:
public void RegisterHandler(object handler)
{
var handled = from iface in handler.GetType().GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() == typeof(IWorker<>)
select iface.GetGenericArguments()[0];
foreach (var type in handled)
{
if (!RegisteredWorkers.ContainsKey(type))
{
Action<IWorkItem> handleAction = HandlerAction(type, handler);
RegisteredWorkers[type] = handleAction;
}
}
}
public void Process(IWorkItem item)
{
Action<IWorkItem> handleAction = RegisteredWorkers[item.GetType()];
handleAction(item);
}
private static Action<IWorkItem> HandlerAction(Type itemType, object handler)
{
var paramExpr = Expression.Parameter(typeof(IWorkItem));
var castExpr = Expression.Convert(paramExpr, itemType);
MethodInfo processMethod = typeof(IWorker<>).MakeGenericType(itemType).GetMethod("Process");
var invokeExpr = Expression.Call(Expression.Constant(handler), processMethod, castExpr);
var lambda = Expression.Lambda<Action<IWorkItem>>(invokeExpr, paramExpr);
return lambda.Compile();
}