Extension method for generic type with additional parameters of general type

I would like to write an extension method for a generic type with additional parameters of a generic type. I already have working code, but I donโ€™t like the result, because the user must re-enter the type parameters of the existing type.

I have a specific example, but keep in mind that this is a common problem. I appreciate feedback on a specific problem, but I am looking for common solutions.

For a class like Action<T> add an extension method with a signature like this:

 Func<T, TResult> ToFunc<TResult>(); 

Here is my working code:

 public static class DelegateExtensions { public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action) { return arg => { action(arg); return default(TResult); }; } } 

But use stinks:

 public void TakesAFunc(Func<int, float> someFunc) { /* ... */ } // ... Action<int> someIntAction = /* ... */; TakesAFunc(someIntAction.ToFunc<int, float>()); 

In this example, the generic int parameter is the only valid value, so it causes unnecessary code duplication.

Type inference doesn't work here. I think this is because you cannot infer a generic parameter through the return type.

This code will solve the problem, but unfortunately does not work:

 public static class DelegateExtensions<T> { public static Func<T, TResult> ToFunc<TResult>(this Action<T> action) { return arg => { action(arg); return default(TResult); }; } } 

Usage will be as you expected:

 public void TakesAFunc(Func<int, float> someFunc) { /* ... */ } // ... Action<int> someIntAction = /* ... */; TakesAFunc(someIntAction.ToFunc<float>()); 

I noticed that System.Linq.Queryable works like my first piece of code, although usually it doesn't need additional type parameters, so type inference works.

Is there any known trick requiring these repeating typical type parameters? One thought that comes to mind will be code generators or macros, but I can't figure out how I would do it cleanly.

+4
source share
2 answers

One common trick for this kind of thing is to pass a dummy value of the desired type only for type inference, which is required in certain scripts associated with anonymous types.

 public static class DelegateExtensions { public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action, TResult ignored) { return arg => { action(arg); return default(TResult); }; } } 

How good the trick is depends on personal opinion, but it confuses me every time I call it, and every time I return to the place I called. You can also change the semantics of the method so that the second parameter is a return value, allowing the caller to decide whether they want default values โ€‹โ€‹or not.

As for your second example, I'm sure extension methods are not allowed for generic types, but I don't have a link convenient

+3
source

I'm late for the party - sorry.

As already mentioned, this is currently not possible without switching the Func parameter to out.

I will throw another way to do this - it seems to me that this looks a bit fluid syntax, but it works.

  public class ActionWrap<T> { private readonly Action<T> _action; internal ActionWrap(Action<T> action) { _action = action; } public Func<T, TResult> OfType<TResult>() { return arg => { _action(arg); return default(TResult); }; } } public static class DelegateExtensions { public static ActionWrap<T> ToFunc<T>(this Action<T> action) { return new ActionWrap<T>(action); } } 

Then his call:

 Action<int> x = z=> Console.WriteLine(z); Func<int, float> asFunc = x.ToFunc().OfType<float>(); 

This is not exactly what you wanted, but it aims to not provide general information again and can be extended to other cases when you want to do something like that.

+2
source

Source: https://habr.com/ru/post/1332290/


All Articles