Func<> is very convenient in .NET. Is there a way i can specify the param type and have the result value as void? I'd like to pass void Write(string) as a parameter.
Action<T> - "Encapsulates a method that takes a single parameter and does not return a value"
I believe you're looking for the Action<T> family of delegate types.
It's not perfect, but sometimes when I want to fake this behavior against an existing function (and I'd rather not re-implement it as Action<TResult>) I'll just return null and throw the value away.
Func<T, TResult> myFunc = (inVar) =>
{
// do work...
return null as object;
};
Related
In this answer, I wrote a LINQ extension that utilizes the following delegate, so I can pass in a function with an out variable, such as int.TryParse:
public delegate bool TryFunc<TSource, TResult>(TSource source, out TResult result);
public static IEnumerable<TResult> SelectTry<TSource, TResult>(
this IEnumerable<TSource> source, TryFunc<TSource, TResult> selector)
{
foreach (TSource item in source)
{
TResult result;
if (selector(item, out result))
{
yield return result;
}
}
}
In order to use this extension, I have to explicitly specify the <string, int> types like so:
"1,2,3,4,s,6".Split(',').SelectTry<string, int>(int.TryParse); // [1,2,3,4,6]
I want to remove <string, int>, similar to how we can call .Select(int.Parse) without specifying <int>, but when I do, I get the following error:
The type arguments for method 'LINQExtensions.SelectTry(IEnumerable, LINQExtensions.TryFunc)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
My question is, why can't the types be inferred? My understanding is that the compiler should know the signatures of int.TryParse and subsequently the TryFunc delegate at compile time.
It can't be inferred because only one of those arguments fits and that's the string. The 2nd parameter is the out int and that cannot be specified in the generic arguments which is why it is saying the arguments cannot be inferred.
The only way to call SelectTry without specifying arguments is by declaring your delegate somewhere that points to int.TryParse and then passing it in as your parameter.
I know this isn't what you want, this is the only way I know of getting around specifying the arguments.
TryFunc<string, int> foo = int.TryParse;
var s = "1,2,3,4,s,6".Split(',').SelectTry(foo);
Remember, in order to pass in methods as delegates, the parameters must match 1:1. int.TryParse matches TryFunc, but it does not match SelectTry
I'm trying to create an extension method for Moq where I can send in an expression to be used in an async return function. However this question is not really Moq specific. Here's what I have so far:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult, T>(this IReturns<TMock, Task<TResult>> setup, Func<T, TResult> valueFunc) where TMock : class
{
return setup.Returns(Task.FromResult(valueFunc.Invoke(default(T))));
}
This is how I'm hoping to use it.
repo.Setup(x => x.FindAsync(It.IsAny<Expression<Func<T, bool>>>())).ReturnsAsync((Expression<Func<T, bool>> e) => context.GetSet<T>().FirstOrDefault(e));
Now I don't really know how all of this works and the thing I can't figure out is how to I get the expression passed on into the ReturnsAsync function so I can use it as the argument instead of the default(T) that I put there as a placeholder.
As expected the "e" variable here becomes null.
This method will do what you want:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult, T>(
this IReturns<TMock, Task<TResult>> setup,
Func<Expression<Func<TResult, T>>, TResult> valueFunc)
where TMock : class
{
return setup.Returns<Expression<Func<TResult, T>>>(
e => Task.FromResult(valueFunc(e)));
}
Then use it like so:
repo.Setup(x => x.FindAsync(It.IsAny<Expression<Func<T, bool>>>()))
.ReturnsAsync<IRepository, int, bool>(e => context.GetSet<T>().FirstOrDefault(e));
Essentially, this version of ReturnsAsync takes a function that expects a predicate function (which is e) and returns a T. This allows you to then execute the predicate against your test data set (context.GetSet<T>.FirstOrDefault). Also, I used the overload of Returns that accepts a type parameter; this is used to forward the arguments from the Setup call to the function specified as the Returns argument.
Your version's signature only specified the predicate, so you had no way to execute it against your test data. You also had the T and TResult type parameters backwards in the valueFunc parameter's type.
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
How can I supply a func to a method, so I could write something like:
MethodTest(a => a.IsAltTagAvailable);
Where the signature of this method takes a func which returns an object (say HtmlImage) when the condition is met (basically just a predicate).
Edit: I need to pass the type I will be working on as T (Parameter). I forgot to do this, how clumsy!
Thanks
A predicate tends to return bool, not an object. What are you going to return when the condition isn't met? Given your example, you don't really mean the function returns an object - you mean it takes an object and returns a bool.
Note that if you're going to have a parameter in the lambda expression, you'll need to use a delegate which takes parameters too.
We really need more information before giving a definitive answer, but you might want something like:
void MethodTest(Func<HtmlImage, bool> predicate)
or
void MethodTest(Predicate<HtmlImage> predicate)
(Personally I like the descriptive nature of using a named delegate, but others prefer to use Func/Action for almost everything.)
That's assuming that the type of input is fixed. If not, you might want to make it a generic method:
void MethodTest<T>(Predicate<T> predicate)
void MethodTest(Func<HtmlImage> func) {
}
void MethodTest(Func<HtmlImage, object> func)
{
}
HtmlImage is the argument of the function (x), object the return value, you could take the concrete type if you want to specify it.
void MethodTest(Func<HtmlImage, bool> func)
Which is a predicate:
void MethodTest(Predicate<HtmlImage> func)
To make it fully generic, replace HtmlImage with a generic argument:
void MethodTest<T>(Predicate<T> func)
public void MethodTest(Func<HtmlImage> delegate)
{
//do what you want
}
OR:
public delegate HtmlImageTagHandler(HtmlImage image);
public HtmlImage MethodTest(HtmlImageTagHandler handler, HtmlImage image)
{
return handler(image) == true ? image : null;
}
use:
MethodTest(a => a.IsAltTagAvailable, a);
I am trying to create a class that lets me call methods with a specified timout. I have the actual timeout implementation working, but am having trouble encapsulating this into a class successfully.
I have decided at this time to limit myself to working with just the 5 Action delegates to put a timeout on methods that take 0 - 4 arguments. For the purposes of this question i will use the one argument variant of Action.
My Ideal calling syntax would be something like this:
Action<int> a = new TimeoutAction(i => i + 1)
{
Timeout = Timespan.FromSeconds(10)
}
or this:
Action<int> a = (x => x + 1).Timeout(Timespan.FromSeconds(10))
I am almost sure that the first version isnt possible as there is no way to inherit from a delegate. The second may be possible by using an extension method on the Delegate type.
A final fallback would be to create static methods that take in the appropriate delegate type and return a Delegate with the same signature but with the timeouts included.
Any suggestions or ideas?
Your last suggestion would be the right way:
A final fallback would be to create
static methods that take in the
appropriate delegate type and return a
Delegate with the same signature but
with the timeouts included.
In other words:
public static Action<T> Timeout<T>(this Action<T> action, TimeSpan timeSpan);
public static Action<T1, T2> Timeout<T1, T2>(this Action<T1, T2> action, TimeSpan timeSpan);
public static Func<T, TResult> Timeout<T, TResult>(this Func<T, TResult> action, TimeSpan timeSpan);
public static Func<T1, T2, TResult> Timeout<T1, T2, TResult>(this Func<T1, T2, TResult> action, TimeSpan timeSpan);
/* snip the rest of the Action<...> and Func<...> overloads */
"Why can't I just declare one method?"
You could declare one method that accepts a Delegate and returns a Delegate, but then you'd lose the delegate type information (your second example wouldn't compile).
Unfortunately, the following example isn't valid C# -- you can't use Delegate as a type parameter constraint:
public static TDelegate Timeout<TDelegate>(this TDelegate d, Timespan timespan) where TDelegate : Delegate;
Use AOP for that. Either PostSharp or DynamicProxy
How about something like the approach to a Timed Lock as described here?
Well, a lambda expression won't "have a type" (anything you can 'dot' or extension method) until you wrap it in e.g.
new DelType(lambda)
or
Stat.Method(lambda)
or otherwise provide context, so I suggest the final option (static method):
Timeout.Action(lambda, timeoutVal)