我需要一个采用Action(或Func)的方法,但Action有一个混合数量的参数.实现这些重载的最直接,最紧凑的方法是什么:
public void Execute<T>(Action<T> action, T param) {
// TODO: Implement something like:
// Execute(action, param, null);
}
public void Execute<T1,T2>(Action<T1,T2> action, T1 param1, T2 param2) {
// TODO: Implement something like:
// Execute(action, param1, param2, null);
}
public void Execute<T1,T2,T3>(Action<T1,T2,T3> action, T1 param1, T2 param2, T3 param3) {
DoStuff();
action(param1, param2, param3)
DoMoreStuff();
}
// OR any other type of higher order function-solution
public void Execute(Action action, params object[] parameters) { ... } // ???
Run Code Online (Sandbox Code Playgroud)
除了执行操作及其参数之外,方法的内容完全相同.
如果可能,请不要使用任何特定于C#4.0的功能来解决此问题.
如果我尝试写一个方法的两个重载,一个接受Expression<Func<T>>参数而另一个接受a Func<T>,我将在尝试使用lambda表达式调用该方法时遇到编译器错误,因为这两个签名会产生歧义.以下是有问题的,例如:
Method(() => "Hello"); // Is that a Func<string>,
// or is it an Expression<Func<string>>?
Run Code Online (Sandbox Code Playgroud)
我明白了.但是我不喜欢只接受一个的方法Expression<Func<string>>,因为这会强制调用代码来使用lambda表达式.如果我也希望能够接受方法组怎么办?
我提出这个问题的基础是,我正在编写一些代码,我希望能够编写这样的代码:
Method(() => "Hello");
Run Code Online (Sandbox Code Playgroud)
...并获得如下输出:
Executed '() => "Hello"' and got "Hello" back.
同时,我也希望能够做到这一点:
Method(ReturnHello);
Run Code Online (Sandbox Code Playgroud)
...并获得如下输出:
Executed 'ReturnHello' and got "Hello" back.
有没有办法做我正在尝试做的事情,而不只是使用两个不同的方法名称(例如,ExpressionMethod和FuncMethod)?我意识到这不会是一件大事; 我只是好奇,如果有另一种方式.
我有以下两个功能,几乎相同,唯一的区别是一个使用func,另一个action.如果可能的话,我想将它们组合成一个函数.
private static void TryCatch(Action action)
{
try
{
action();
}
catch (Exception x)
{
Emailer.LogError(x);
throw;
}
}
private static TResult TryCatch<TResult>(Func<TResult> func)
{
try
{
return func();
}
catch (Exception x)
{
Emailer.LogError(x);
throw;
}
}
Run Code Online (Sandbox Code Playgroud) 我有很多方法需要一些具有相同模式的日志记录.有些方法需要返回一些值,有些则不需要.我已经创建了一个带有Action参数的方法,以避免对所有逻辑进行复制.它看起来像这样:
private void Execute(Action action)
{
Logger.Start();
try
{
action();
}
catch(Exception exception)
{
Logger.WriteException();
throw;
}
finally
{
Logger.Finish();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我有一些类似的电话
public void DoSomething(string parameter)
{
Execute(() => GetProvider(parameter).DoSomething());
}
Run Code Online (Sandbox Code Playgroud)
但我需要一些返回值的函数.最好的方法是什么?我现在找到了两个:
1)使用Func创建Execute方法的副本
private T Execute<T>(Func<T> action)
{
Logger.Start();
try
{
return action();
}
catch(Exception exception)
{
Logger.WriteException();
throw;
}
finally
{
Logger.Finish();
}
}
Run Code Online (Sandbox Code Playgroud)
此方法有效,但也有一些复制粘贴.
2)将参数欺骗为动作:
public Result DoSomething(string parameter)
{
Result result = null;
Execute(() => result = GetProvider(parameter).DoSomething());
return result;
}
Run Code Online (Sandbox Code Playgroud)
这不需要复制粘贴,但看起来不太好.
有没有办法以某种方式加入Action和Func以避免任何这些方法,或者可能有另一种方法来实现相同的结果?
如何Func<>在C#中获取Lambda 的传递参数的值
IEnumerable<AccountSummary> _data = await accountRepo.GetAsync();
string _query = "1011";
Accounts = _data.Filter(p => p.AccountNumber == _query);
Run Code Online (Sandbox Code Playgroud)
这是我的扩展方法
public static ObservableCollection<T> Filter<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
{
string _target = predicate.Target.ToString();
// i want to get the value of query here.. , i expect "1011"
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
我想在分配给_target的Filter扩展方法中获取查询的值
我正在尝试将linq写入实体扩展方法,该方法使用Func选择属性Id并将其与ID列表进行比较.
类
public class A
{
public int AId { get; set; }
}
public class B
{
public int BId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
扩展方法
public static IQueryable<T> WithId<T>(this IQueryable<T> entities,
Func<T, int> selector, IList<int> ids)
{
Expression<Func<T, bool>> expression = x => ids.Contains(selector(x));
return entities.Where(expression); // error here (when evaluated)
}
Run Code Online (Sandbox Code Playgroud)
呼叫方法
var ids = new List<int> { 1, 2, 3 };
DbContext.EntityAs.WithId(e => e.AId, ids);
DbContext.EntityBs.WithId(e => e.BId, ids);
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是它试图调用Entity Framework中不允许的功能.
如何使用属性选择器(Func)来评估查询?
为什么以下编译?看起来好像编译器有足够的信息知道尝试的赋值是无效的,因为Func <>的返回类型不是动态的.
Func<dynamic, int> parseLength = whatever => whatever.Length;
dynamic dynamicString = "String with a length";
DateTime wrongType = parseLength(dynamicString);
Run Code Online (Sandbox Code Playgroud) 从C#7.0开始,throw关键字既可以用作表达式,也可以用作语句,这很好.但是,请考虑这些过载
public static void M(Action doIt) { /*use doIt*/ }
public static void M(Func<int> doIt) { /*use doIt*/ }
Run Code Online (Sandbox Code Playgroud)
在调用时这样
M(() => throw new Exception());
Run Code Online (Sandbox Code Playgroud)
或者甚至喜欢这样(带有语句lambda)
M(() => { throw new Exception(); });
Run Code Online (Sandbox Code Playgroud)
编译器选择M(Func <>)重载,指示throw在这里被视为表达式.如何优雅和明确地强制编译器选择M(Action)重载?
一种方法是这样做
M(() => { throw new Exception(); return; });
Run Code Online (Sandbox Code Playgroud)
但返回语句的原因似乎并不明显,并且存在被下一个开发人员更改的风险,特别是因为Resharper警告无法访问的代码.
(当然我可以更改方法命名以避免重载,但这不是问题.:-)
我有一个方法(fyi,我正在使用c#),接受一个类型为"Func"的参数,让我们说它是这样定义的:
MethodAcceptingFuncParam(Func<bool> thefunction);
Run Code Online (Sandbox Code Playgroud)
我已经定义了要传递的函数:
public bool DoStuff()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
我可以很容易地称之为:
MethodAcceptingFuncParam(() => { return DoStuff(); });
Run Code Online (Sandbox Code Playgroud)
这应该是应有的,到目前为止一切顺利.
现在,我想通过反射创建这个方法,而不是传入DoStuff()方法,并将其传递给:
Type containingType = Type.GetType("Namespace.ClassContainingDoStuff");
MethodInfo mi = containingType.GetMethod("DoStuff");
Run Code Online (Sandbox Code Playgroud)
=>这个工作,我可以正确获取methodinfo.
但这就是我被困的地方:我现在想做点什么
MethodAcceptingFuncParam(() => { return mi.??? });
Run Code Online (Sandbox Code Playgroud)
换句话说,我想通过反射传递方法作为MethodAcceptingFuncParam方法的Func参数的值.关于如何实现这一点的任何线索?
我最近一直在玩代理Func<T, TResult>并创建返回Func<T, TResult>包含lambda的不同实例的方法,但我一直在努力想出的是为什么人们想要返回(甚至创建这样的实例)的任何好的现实世界观点.
在MSDN上有一个例子,它们执行以下操作......
Func<string, string> convertMethod = UppercaseString;
private static string UppercaseString(string inputString)
{
return inputString.ToUpper();
}
Run Code Online (Sandbox Code Playgroud)
虽然它看起来很漂亮并且是一个有趣的概念,但我没有看到这些代码提供的优势.
那么有人可以提供他们必须使用的任何现实世界的例子,Func<T, TResult>并且一般为什么人们可能想要使用这个代表?
func ×10
c# ×9
action ×4
expression ×3
lambda ×3
.net ×2
delegates ×2
overloading ×2
c#-4.0 ×1
dynamic ×1
linq ×1
methods ×1
parameters ×1
refactoring ×1
reflection ×1