Compile Error 'cannot convert' on Declared Delegate - c#

I'm having issues when passing a delegate as a Where parameter in LINQ.
I'm declaring a delegate in the namespace:
public delegate bool FilterInt<in T>(T x);
I've made a method to assign to the delegate and then assign it:
public static bool FilterData(int val)
{
if (val < 10)
return true;
return false;
}
When I try to filter a List using the delegate I get a compile time error 'Cannot conver from FilterInt to Func<Int, bool>:
listInt.Where(_filterer);
However, I can use the below (an implied delegate?) without any issues:
listInt.Where(FilterData);
I have the same issue with _comparer when I follow the MSDN doc on delegates here if I define my own delegate in the namespace as per the below:
public delegate int Comparison<in T>(T x, T y);
public static int CompareLength(string left, string right) =>
right.Length.CompareTo(left.Length);
readonly Comparison<string> _comparer = CompareLength;
list.Sort(_comparer);
However, if I omit the initial declaration of Comparison, it works fine (note - Comparison exists in the System namespace).
I assume it's an issue with my initial delegate declaration.

Enumerable.Where accepts Func<TSource, bool> delegate. If you look for documentation on Func<T,TResult> you will find out that it is declared as:
public delegate TResult Func<in T,out TResult>(T arg);
So you will need to "convert" your delegate into instance of Func<TSource, bool> which is possible either with direct creation an instance of the delegate:
new[] { 1 }.Where(new Func<int, bool>(_filterer));
Or with anonymous (lambda) function:
new[] { 1 }.Where(i => _filterer(i));
Which is actually a syntactic sugar transformed by compiler into something like this:
// generated class to hold your lambda:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public FilterInt<int> _filterer;
// your lambda:
internal bool <M>b__0(int i)
{
return _filterer(i);
}
}
// instantiation of new Func<int, bool>
Enumerable.Where(array, new Func<int, bool>(<>c__DisplayClass0_.<M>b__0));
Method group call (listInt.Where(FilterData);) also is syntactic sugar expanded by compiler into creation of new delegate:
Enumerable.Where(array, new Func<int, bool>(FilterData));

You can call like this.
Where(new Func<int, bool>(FilterInt))
Or
.Where(x => FilterInt(x))

The error occurs because of the where clause expects a Func<TSource, TResult> with a Boolean as TResult and not just a Func<int> as its representative.
IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
The closest way to use it as you wish will be something like this, but I don't believe it as a good implementation.
using System;
using System.Collections.Generic;
using System.Linq;
public delegate Func<T1, T2> FilterInt<in T1, out T2>(T1 value);
namespace DelegateTest
{
class Program
{
private static readonly List<int> List = new List<int> {0, 1, 2, 10, 11, 12};
static void Main(string[] args)
{
FilterInt<int, bool> filterInt = FilterData;
var result = List.Where(x => filterInt.Invoke(x).Invoke(x));
foreach (var item in result) Console.WriteLine(item.ToString());
}
private static Func<int, bool> FilterData(int value) => _ => value < 10;
}
}

Related

How to cast Predicate<T> to Func<T, bool> [duplicate]

I have a class with a member Predicate which I would like to use in a Linq expression:
using System.Linq;
class MyClass
{
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(m_filterExpression);
}
private IEnumerable<Instrument> m_instrumentList;
private Predicate<Instrument> m_filterExpression;
}
As I read that "Predicate<T> is [...] completely equivalent to Func<T, bool>" (see here), I would expect this to work, since All takes in as argument: Func<Instrument, bool> predicate.
However, I get the error:
Argument 2: cannot convert from 'System.Predicate<MyNamespace.Instrument>' to 'System.Type'
Is there a way to convert the predicate to an argument that this function will swallow?
The two types represent the same logical signature, but that doesn't mean they're just interchangable. A straight assignment won't work, for example - but you can create a new Func<T, bool> from the Predicate<T, bool>. Sample code:
Predicate<string> pred = x => x.Length > 10;
// Func<string, bool> func = pred; // Error
Func<string, bool> func = new Func<string, bool>(pred); // Okay
This is a bit like having two enum types with the same values - you can convert between them, but you have to do so explicitly. They're still separate types.
In your case, this means you could write:
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(new Func<T, bool>(m_filterExpression));
}
The lambda expression approach suggested by other answers will work too, of course.
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(i => m_filterExpression(i));
}
You can convert a predicate to a method by calling Invoke. All delegates have this member. Delegates don't have structural identity, but methods can be converted to matching delegates. This fix has a minor performance cost, as it adds an extra layer of indirection. However, most solutions to this problem have that problem. Eric Lippert discusses this in more detail at https://web.archive.org/web/20140625132124/http://blog.coverity.com/2014/06/18/delegates-structural-identity/ .
In your specific case, replace return m_instrumentList.All(m_filterExpression); with return m_instrumentList.All(m_filterExpression.Invoke);
Sample code demonstrating the actual problem.
void Main()
{
Predicate<int> t1 = Foo;
Func<int,bool> t2 = Foo;
Predicate<int> t3 = t2.Invoke; //Legal
Func<int,bool> t4 = t1.Invoke; //Legal
Predicate<int> t5 = t2; //Illegal
Func<int,bool> t6 = t1; //Illegal
}
bool Foo(int x)
{
return x > 20;
}
return m_instrumentList.All(i => m_filterExpression(i));
Since there are a lot of answers i will add one more just for fun.
If you want your code to compile you can use extention methods
//Original Code
class MyClass4
{
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(m_filterExpression);
}
private IEnumerable<Instrument> m_instrumentList;
private Predicate<Instrument> m_filterExpression;
}
Add this class in the same namespace
public static class MyExtentions
{
public static bool All(this IEnumerable<Instrument> enumer, Predicate<Instrument> pred)
{
return enumer.All(e => pred(e));
}
}
As Brian said, you can convert a predicate to a method via Invoke:
public bool DoAllHaveSomeProperty()
{
return m_instrumentList.All(m_filterExpression.Invoke);
}

Use generic type parameter in a Func, and invoke Func with specific type?

I have the following method where T is used inside a Func:
public void DoSomething<T>(string someString, Func<T, bool> someMethod)
{
if(someCondition)
{
string A;
bool resultA = someMethod(A);
}
else
{
string[] B;
bool resultB = someMethod(B);
}
// Some other stuff here ...
}
I am invoking the DoSomething method in the following manner:
DoSomething<string>("abc", someMethod);
DoSomething<string[]>("abc", someMethod);
And the someMethod exists with the following definitions:
bool someMethod(string simpleString);
bool someMethod(string[] stringArray);
Now the compilation fails with the following errors in method DoSomething:
cannot convert from 'string' to 'T'
cannot convert from 'string[]' to 'T'
I am unable to figure out if there is a solution to the problem, or what I am trying is not feasible. It looks similar to question How can I pass in a func with a generic type parameter?, though it was not helpful for my scenario.
Your example seems a little inconsistent, but if you were writing things generically, it should look more like this:
public void DoSomething<T>(string someString, Func<T, bool> someMethod)
{
T a;
someMethod(a);
}
Notice that instead of using if to choose between types, and then declaring the type as either a string or string[], we simply declare the type as T, which will get substituted when the code is compiled so that it will be appropriate for the function.
The moment you find yourself picking between types using if or switch case, you probably don't want a generic solution; the logic isn't, in fact, generic at all. It is specific. In that sort of case, just write two prototypes:
public void DoSomething(string someString, Func<string, bool> someMethod)
{
string A;
bool resultA = someMethod(A);
}
public void DoSomething(string someString, Func<string[], bool> someMethod)
{
string[] A;
bool resultA = someMethod(A);
}
This is known as method overloading. The compiler will automatically pick the right method with the right arguments by inferring the types from the supplied function.
You can achieve it via reflection:
public void DoSomething<T>(string someString, Func<T, bool> someMethod)
{
var args = new Dictionary<Type, object>
{
[typeof(string)] = "string", //string A;
[typeof(string[])] = new[] { "string" }, //string[] B;
};
var arg = args[typeof(T)];
var result = (bool)someMethod.Method.Invoke(someMethod.Target, new[] { arg });
}
Usage:
DoSomething<string>("abc", someMethod);
DoSomething<string[]>("abc", someMethod);

Overloading a generic extension method

I have a problem overloading an extension method.
I have two extension Methods:
Method A - For standard objects:
public static bool HasChanged<T>(this T obj1, T obj2, Func<T, T, bool> equalityExpression)
Method B - For IEnumerables:
public static bool HasChangedList<T>(this IEnumerable<T> obj1, IEnumerable<T> obj2, Func<T, T, bool> isEqualExpression)
But I would like to give them both the same names, that is currently not working, cause IEnumerables are objects aswell, so the compiler isnt able to decide whether to use the first one or the second one on an IEnumerable.
I am sure, its not possible to let first method take all object but an IEnumerable, so is there another way around?
(Not really a solution, but too long for a comment. Hopefully, one of the C# spec gurus will show up and tell us why overload resolution works like this in this particular case.)
If
you qualify the parameters of your equalityExpression or if
the inner type of the IEnumerable can be inferred from the lambda expression,
it should work fine:
class Program
{
static void Main(string[] args)
{
var array = new[] { 1, 2, 3 };
// uses the IEnumerable overload -- prints false
Console.WriteLine(array.HasChanged(array, (int x, int y) => x == y));
// uses the IEnumerable overload -- prints false
Console.WriteLine(array.HasChanged(array, (x, y) => x >= y));
// uses the generic overload -- prints true
Console.WriteLine(array.HasChanged(array, (x, y) => x == y));
Console.ReadLine();
}
}
static class Extensions
{
public static bool HasChanged<T>(this IEnumerable<T> obj1, IEnumerable<T> obj2, Func<T, T, bool> isEqualExpression)
{
return false;
}
public static bool HasChanged<T>(this T obj1, T obj2, Func<T, T, bool> equalityExpression)
{
return true;
}
}

Can a lambda expression be declared and invoked at the same time in C#?

In VB.NET, a lambda expression can be declared and invoked on the same line:
'Output 3
Console.WriteLine((Function(num As Integer) num + 1)(2))
Is this possible in C#?
You have to tell the compiler a specific delegate type. For example, you could cast the lambda expression:
Console.WriteLine(((Func<int, int>)(x => x + 1))(2));
EDIT: Or yes, you can use a delegate creation expression as per Servy's answer:
Console.WriteLine(new Func<int, int>(i => i + 1)(2));
Note that this isn't really a normal constructor call - it's special syntax for delegate creation which looks like a regular constructor call. Still clever though :)
You can make it slightly cleaner with a helper class:
public static class Functions
{
public static Func<T> Of<T>(Func<T> input)
{
return input;
}
public static Func<T1, TResult> Of<T1, TResult>
(Func<T1, TResult> input)
{
return input;
}
public static Func<T1, T2, TResult> Of<T1, T2, TResult>
(Func<T1, T2, TResult> input)
{
return input;
}
}
... then:
Console.WriteLine(Functions.Of<int, int>(x => x + 1)(2));
Or:
Console.WriteLine(Functions.Of((int x) => x + 1)(2));
Console.WriteLine(new Func<int, int>(i => i + 1)(2));
Uses a few less parentheses to use the Func's constructor than a cast.
Yes, though it's messy:
Console.WriteLine(((Func<int, int>) (num => num + 1))(2));
Kind or, you would have to use the Func object :
var square = new Func<double, double>(d => d*d)(2);
Console.WriteLine(square);

C#: Func<T, TResult> for generic methods

It is possible to create a Func object what references a generic method? like the LINQ OrderBy:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
If I understand you correctly, you're asking if you can reference a generic method from within an anonymous method.
The answer is yes.
For example, suppose you want some Func that returns the elements of an IEnumerable<int> object in sorted order (precisely like OrderBy<int, int>). You could do this:
Func<IEnumerable<int>, Func<int, int>, IOrderedEnumerable<int>> orderByFunc =
System.Linq.Enumerable.OrderBy<int, int>;
Then you could use this Func just like any other:
int[] ints = new int[] { 1, 3, 5, 4, 7, 2, 6, 9, 8 };
// here you're really calling OrderBy<int, int> --
// you've just stored its address in a variable of type Func<...>
foreach (int i in orderByFunc(ints, x => x))
Console.WriteLine(i);
Output:
1
2
3
4
5
6
7
8
9
On the other hand, if you're asking whether it's possible to create a "generic anonymous method," like this:
Func<T> getDefault<T> = () => default(T);
Then it depends on your context. This can be done from within a context where T is already declared as a generic type parameter -- namely, within a generic class or generic method. (See Freddy Rios's answer.) Outside of such a context, unfortunately, it is illegal.
Yes, but it depends on the context - if you are already working with generics, just use the T in the context / if not, then you already know the specific type. In the later, if you need to reuse a bit of logic on a method, u probably already would benefit of moving that into a method, so just do like my second example below.
2 samples:
public T Something<T>() {
Func<T> someFunc = () => { return default(T); };
return someFunc();
}
public Func<T> GetDefaultCreator<T>() {
return () => { return default(T); };
}
Something like this?
Func<Nullable<int>, string> myFunc = c => c.HasValue ? c.ToString() : "null";
That successfully compiles, and you could assign any function to that that takes in a Nullable and returns a string.
I have done something like this:
public static class Helper{
public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection Form)
{
return Form.AllKeys.Cast<string>()
.Select(key => new KeyValuePair<string, string>(key, Form[key]));
}
}
Where this method has become an extension method to the request.form in C# web development.
I think I get it: Given the function static TResult DoSomeStuff<T, TResult>(T obj), can you create a Func<T, TResult> such that it will reference the function above, with no type parameters given at the creation of the reference to it.
I think this could work (You're welcome to test it, I have no C# near me at the moment):
class UselessClass<T, TResult>
{
// If it's a static method, this is fine:
public Func<T, TResult> DaFunc = RelevantClass.DoSomeStuff<T, TResult>;
// If not, something like this is needed:
public UselessClass(SomeClassWhereTheFunctionIs from)
{
DaFunc = from.DoSomeStuff<T, TResult>;
}
}
Also, in OrderBy, it's not actually a generic delegate. It's a declaration of a variable. When the function is given to it, the types are inferred from it.
Yes it's possible but you'll need to specify the type argument(s)
func<int> f = myClass.returnsT<int>;
where
class myClass
{
T returnsT<T>()
{...}
}
it Will not work without the type arguments

Categories