defining a generic action that takes a generic action as parameter - c#

I am using .Net 4.5. How do I define a generci action that takes in another generic action as a parameter?
When I try the following, the compiler seems to interpret T as an actual type and complains that its definitions is not found:
public static Action<Action<T>, IEnumerable<T>> RepeatForEach = (a, x) =>
{
foreach (T t in x)
{
a.Invoke(t);
}
};
I tried the following, none of which worked:
Action<T><Action<T>>
Action<Action<T>><T>
Action<Action<T>> where T : object

I dont think it is possible to create a generic type based upon another generic. As said by sstan:
"Even generic types need to be declared somewhere."
Instead you should try another approach, what about you create an extention method instead? This is my sugestion:
public static void RepeatForEach(this Action<T> action, IEnumerable<T> itens)
{
foreach (T t in x)
{
a.Invoke(t);
}
}
So you can call it by:
Action<int> t = (int i)=> Console.WriteLine(i);
t.RepeatForEach(myitens)

I'm afraid that C# doesn't support this level of genericity. You will have to make the enclosing scope generic.
Either have a class:
public static class RepeatForEach<T>
{
public static Action<Action<T>, IEnumerable<T>> Action = (action, enumerable)
{
foreach (var element in enumerable)
{
action.Invoke(element);
}
}
}
Or have a method returning the action:
public static class MyClass
{
public static Action<Action<T>, IEnumerable<T>> GetRepeatForEachAction<T>()
{
return (action, enumerable) =>
{
foreach (var element in enumerable)
{
action.Invoke(element);
}
}
}
}
I'd also like to put forth an idea that having something do foreach on IEnumerable is generally a very bad idea. The reason for that would be to achieve side effects and IEnumerable is not built for that.
Imagine having an IEnumerable created via yield return. Then your action might not affect any of the elements (as those may be thrown away and recreated upon enumeration).

Related

LINQ Select - CS0411 The type arguments cannot be inferred from the usage - What am I doing wrong?

Goal: ForEach extension masking Select.
Reason: Select allows for method chaining while foreach does not; ForEach is more readable than Select.
The problem I'm running into is that I'm getting this error.
The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. (CS0411)
public static void ForEach<T>(this IEnumerable<T> elements, Action<T, int> action)
{
elements.Select((elem, i) => action(elem, i));
}
I've tried doing elements.Select((T elem, int i) => action(elem, i)); but that produces the same error.
I've also attempted using Func instead of Action but there doesn't seem to be any way to use void for the return (which is what Action is for anyways). If I define the method to take a Func instead of Action then when I try to call it using Action I get the same error.
public static IEnumerable<TOut> ForEach<TIn, TOut>(this IEnumerable<TIn> elements,
Func<TIn, int, TOut> function)
{
return elements.Select((elem, i) => function(elem, i))
.ToList();
}
I don't understand which arguments cannot be inferred. There are ways I could get around this (using a for loop or foreach loop and track the index), but I would still like to figure out why this won't work.
Edit: I also just realized my other ForEach for Action (no index) also gets this error when I switch from a foreach loop to calling Select.
public static void ForEach<T>(this IEnumerable<T> elements, Action<T> action)
{
elements.ToList().Select((T elem) => action(elem));
/*foreach (var elem in elements)
action(elem);*/
}
The problem is that Select expects a return value (you're projecting an object into something else) - of which your Action is returning void. void can't be converted into T, which is what Select is expecting.
The simple fix is to ensure something is returned at the end of your select function:
public static void ForEach<T>(this IEnumerable<T> elements, Action<T, int> action)
{
elements.Select((elem, i) =>
{
action(elem, i);
return elem;
}).Count();
}
The action is called, and the collection continues to be enumerated. We need to call Count because nothing will actually happen until we attempt to get a value from each enumeration (thank you Jon Skeet!)
Note that this isn't how Select should be used - the OP specifically asked why/how to make it work with it.
To do this properly, as mentioned in the comments, the solution is to use an actual foreach loop with a counter:
public static void ForEach<T>(this IEnumerable<T> elements, Action<T, int> action)
{
int count = 0;
foreach (var item in elements)
{
action(item, count++);
}
}
If you want to allow method chaining, you can do it this way:
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> elements, Action<T, int> action)
{
int count = 0;
foreach (var item in elements)
{
action(item, count++);
yield return item;
}
}

Can I have a different Extension method for IEnumerable<T> than for <T>?

I have an extension method that works on any class, but I want to call a special version if I am working on IEnumerable<T>.
For Example
public static class ExtensionMethods
{
public static dynamic Test<T>(this T source)
{
dynamic expandoObject = new System.Dynamic.ExpandoObject();
var dictionary = (IDictionary<string,object>)expandoObject;
dictionary["Test"] = source.ToString();
return dictionary;
}
public static IEnumerable<dynamic> Test<T>(this List<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
}
// Usage
public class X
{
string guid = Guid.NewGuid().ToString();
}
void Main()
{
List<X> list = new List<X>() { new X() };
list.Test().Dump(); // Correct but only works because there is an explicit overload for List<T>
var array = list.ToArray();
((IEnumerable<X>) array).Test().Dump(); // Correct
array.Test().Dump(); // Calls the wrong extension method
}
Is there any way I can get array.Test() to call the IEnumerable version without having to explicitly cast it?
Alternatively, if I give the extension method different names, if there any way I can get a compiler error if I accidently use the wrong one?
I think you are trying to solve it in a wrong direction. The List implements IEnumerable interface and as such the compiler can have problem with solving the best method will be invoked on List. What you could do -- you could test if the IEnumerable is a list inside the extension method.
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
if (source is List<T>) {
// here
}
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
You can specify T and not rely on type inference, this will hint compiler to use correct extension method. Code would look like this:
var array = list.ToArray();
array.Test<X>().Dump();
What happens is, that compiler cannot tell which extension to use, since Array is valid argument for both method signatures:
public static dynamic Test<T>(this T source) { .. }
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source) { .. }
In first case compiler can assume T is of type Array. Because of it, compiler has to picks one (might be first defined?).
Add this extension method to explicitly catch all array types:
public static IEnumerable<dynamic> Test<T>(this T[] source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}

C# - Make a generic foreach method that accepts any type?

Im busy updating an entity using entity framework and web api (on the PUT method of the controller). For each collection property on the updated object, I loop through and check if each item exists in the collection on the existing object or not. If not, I add it.
The trouble is I have a lot of collections on the object and I find myself repeating the following code many times over.
Is there a way for me to wrap this into a generic method and pass that method the 2 collections to compare? Maybe by specifying the name of the property to check and primary key? How would I be able to specify the type for the foreach loop for example?
foreach (HBGender gender in updated.HBGenders)
{
HBGender _gender = existing.HBGenders.FirstOrDefault(o => o.GenderID == gender.GenderID);
if (_gender == null)
{
//do some stuff here like attach and add
}
}
return existing; //return the modified object
Thanks in advance. I hope this makes sense.
In its simplest form you could write an extension method as such:
public static class IEnumerableExtensionMethods
{
public static ICollection<T> ForEachAndAdd<T>(this IEnumerable<T> self,
ICollection<T> other,
Func<T, T, bool> predicate) where T : class
{
foreach(var h1 in self)
{
if(other.FirstOrDefault(h2 => predicate(h1, h2)) == null)
other.Add(h1);
}
return other;
}
}
Usage:
List<HBGender> updated = new List<HBGender>();
List<HBGender> existing = new List<HBGender<();
return updated.ForEachAndAdd(existing, (h1, h2) => h1.Gender == h2.Gender);
Note that if there is extra logic needed during an add, you could add an additonal Action<T> parameter to do so.
I don't know what you are trying to do, but you can play with this example:
List<object> a = new List<object>();
a.Add("awgf");
a.Add('v');
a.Add(4);
foreach (object b in a)
{
Type type = b.GetType().//Select more usefull
Convert.ChangeType(object,type);
}
Just pass your existing check function, as an extra parameter
public List<Class1> Find(List<Class1> updated, List<Class1> existing, Func<Class1, bool> predicate)
{
foreach (Class1 gender in updated)
{
Class1 _gender = existing.FirstOrDefault(predicate); //predicate for quoted example will be o => o.GenderID == gender.GenderID
if (_gender == null)
{
//do some stuff here like attach and add
}
}
return existing;
}

C# Generics and inferring type

I'm struggling while trying to write generic methods to save and load data from a Sterling database.
This is my save method:
public static void SaveList<T>(List<T> listToSave)
{
foreach (T listItem in listToSave)
{
DatabaseInstance.Save(listItem);
}
}
I get squiggly red line under save and an error of "The Type T must be a reference type in order to use it as parameter T"
This is my load method:
public static List<T> LoadList<T>()
{
List<T> list = (from index in DatabaseInstance.Query<T, int>() select index.Key).ToList();
return list;
}
I get the same error.
Any ideas?
Cheers
Steve
UPDATE:
I added a where T : class as suggested and got an error:
The Type T must have a public parameterless constructor in order to use it as a parameter
Following instructions in the link provided by Bryan I added , new() on the end and all working now.
You need a generic type constraint on your definition:
public static void SaveList<T>(List<T> listToSave) where T : class
{
foreach (T listItem in listToSave)
{
DatabaseInstance.Save(listItem);
}
}
public static List<T> LoadList<T>() where T : class
{
List<T> list = (from index in DatabaseInstance.Query<T, int>() select index.Key).ToList();
return list;
}
To fix your code, you need a generic constraint that forces a reference type, as shown below. To set this answer out from others already posted, I also recommend that you use IEnumerable<T> rather than List<T>:
public static void SaveList<T>(IEnumerable<T> itemsToSave) where T : class
{
foreach (T item in itemsToSave)
{
DatabaseInstance.Save(listItem);
}
}
public static IEnumerable<T> LoadList<T>() where T : class
{
return (from index in DatabaseInstance.Query<T, int>()
select index.Key);
}
The change to IEnumerable<T> should be compatible with all your existing code, as List<T> already implements IEnumerable<T>. Used properly, this will also allow you get a nice performance boost by keeping fewer items at a time in RAM and make your code more powerful by allowing it to work with other collection types.
The problem is that, in your existing code, T can be anything. That's not OK because the Save function only accepts reference types.
You need to place a constraint which effectively makes a commitment to the compiler that T will be a reference type.
public static void SaveList<T>(List<T> listToSave) where T : class
{
foreach (T listItem in listToSave)
{
DatabaseInstance.Save(listItem);
}
}
can you try?
public static void SaveList<T>(List<T> listToSave) where T:class
{
foreach (T listItem in listToSave)
{
DatabaseInstance.Save(listItem);
}
}
Try adding a class constraint:
public static void SaveList<T>(List<T> listToSave) where T : class
{
foreach (T listItem in listToSave)
{
DatabaseInstance.Save(listItem);
}
}
public static List<T> LoadList<T>() where T : class
{
List<T> list = (from index in DatabaseInstance.Query<T, int>()
select index.Key).ToList();
return list;
}

LINQ identity function

Just a little niggle about LINQ syntax. I'm flattening an IEnumerable<IEnumerable<T>> with SelectMany(x => x).
My problem is with the lambda expression x => x. It looks a bit ugly. Is there some static 'identity function' object that I can use instead of x => x? Something like SelectMany(IdentityFunction)?
Unless I misunderstand the question, the following seems to work fine for me in C# 4:
public static class Defines
{
public static T Identity<T>(T pValue)
{
return pValue;
}
...
You can then do the following in your example:
var result =
enumerableOfEnumerables
.SelectMany(Defines.Identity);
As well as use Defines.Identity anywhere you would use a lambda that looks like x => x.
Note: this answer was correct for C# 3, but at some point (C# 4? C# 5?) type inference improved so that the IdentityFunction method shown below can be used easily.
No, there isn't. It would have to be generic, to start with:
public static Func<T, T> IdentityFunction<T>()
{
return x => x;
}
But then type inference wouldn't work, so you'd have to do:
SelectMany(Helpers.IdentityFunction<Foo>())
which is a lot uglier than x => x.
Another possibility is that you wrap this in an extension method:
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
Unfortunately with generic variance the way it is, that may well fall foul of various cases in C# 3... it wouldn't be applicable to List<List<string>> for example. You could make it more generic:
public static IEnumerable<TElement> Flatten<TElement, TWrapper>
(this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
{
return source.SelectMany(x => x);
}
But again, you've then got type inference problems, I suspect...
EDIT: To respond to the comments... yes, C# 4 makes this easier. Or rather, it makes the first Flatten method more useful than it is in C# 3. Here's an example which works in C# 4, but doesn't work in C# 3 because the compiler can't convert from List<List<string>> to IEnumerable<IEnumerable<string>>:
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
}
class Test
{
static void Main()
{
List<List<string>> strings = new List<List<string>>
{
new List<string> { "x", "y", "z" },
new List<string> { "0", "1", "2" }
};
foreach (string x in strings.Flatten())
{
Console.WriteLine(x);
}
}
}
With C# 6.0 and if you reference FSharp.Core you can do:
using static Microsoft.FSharp.Core.Operators
And then you're free to do:
SelectMany(Identity)
With C# 6.0 things are getting better. We can define the identity function in the way suggested by #Sahuagin:
static class Functions
{
public static T It<T>(T item) => item;
}
And then use it in SelectMany the using static constructor:
using Functions;
...
var result = enumerableOfEnumerables.SelectMany(It);
I think it looks very laconic in the such way. I also find the identity function useful when building dictionaries:
class P
{
P(int id, string name) // Sad. We are not getting primary constructors in C# 6.0
{
ID = id;
Name = id;
}
int ID { get; }
int Name { get; }
static void Main(string[] args)
{
var items = new[] { new P(1, "Jack"), new P(2, "Jill"), new P(3, "Peter") };
var dict = items.ToDictionary(x => x.ID, It);
}
}
This may work in the way you want. I realize Jon posted a version of this solution, but he has a second type parameter which is only necessary if the resulting sequence type is different from the source sequence type.
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source)
where T : IEnumerable<T>
{
return source.SelectMany(item => item);
}
You can get close to what you need. Instead of a regular static function, consider an extension method for your IEnumerable<T>, as if the identity function is of the collection, not the type (a collection can generate the identity function of its items):
public static Func<T, T> IdentityFunction<T>(this IEnumerable<T> enumerable)
{
return x => x;
}
with this, you don't have to specify the type again, and write:
IEnumerable<IEnumerable<T>> deepList = ... ;
var flat = deepList.SelectMany(deepList.IdentityFunction());
This does feel a bit abusive though, and I'd probably go with x=>x. Also, you cannot use it fluently (in chaining), so it will not always be useful.
I'd go with a simple class with a single static property and add as many as required down the line
internal class IdentityFunction<TSource>
{
public static Func<TSource, TSource> Instance
{
get { return x => x; }
}
}
SelectMany(IdentityFunction<Foo>.Instance)

Categories