我想我的想法正在爆发,试图找出Funcs ......如果这没有意义,我道歉,现在它对我有意义,但它已经是漫长的一天......
1)假设你有一个func,它接受T并输出一个字符串:
Func<T, string>
Run Code Online (Sandbox Code Playgroud)
你能把它变成一个接受T的函数并根据某些逻辑返回一个bool(在这种情况下,如果返回的字符串为空(String.IsNullOrWhiteSpace)?
Func<T, bool>
Run Code Online (Sandbox Code Playgroud)
如果给你一个,你可以做同样的事吗?
Expression<Func<T, string>>
Run Code Online (Sandbox Code Playgroud)
并需要将其转换为
Func<T, bool>
Run Code Online (Sandbox Code Playgroud)
返回true/false基于返回的字符串是否为空(String.IsNullOrWhiteSpace)?
谢谢
这是一个好奇的问题,你们都知道:
使用Func而不是方法有什么危害/缺点吗?简单的例子:
private static Func<int, int, DBContext, List<T>> Foo =
(i1, i2, dbc) =>
(i1 != 0) ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };
Run Code Online (Sandbox Code Playgroud)
VS
private static List<T> Foo(int i1, int i2, DBContext dbc)
{
return i1 != 0 ? dbc.Bar(i2) : new List<T> { /*some default values ...*/ };
}
Run Code Online (Sandbox Code Playgroud) 例:
public class BusinessTransactionFactory<T> where T : IBusinessTransaction
{
readonly Func<Type, IBusinessTransaction> _createTransaction;
public BusinessTransactionFactory(Func<Type, IBusinessTransaction> createTransaction)
{
_createTransaction = createTransaction;
}
public T Create()
{
return (T)_createTransaction(typeof(T));
}
}
Run Code Online (Sandbox Code Playgroud)
使用相同的容器设置代码:
public class DependencyRegistration : Registry
{
public DependencyRegistration()
{
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory();
x.WithDefaultConventions();
x.AddAllTypesOf(typeof(Repository<>));
x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory();
x.AddAllTypesOf<IBusinessTransaction>();
For(typeof(BusinessTransactionFactory<>)).Use(typeof(BusinessTransactionFactory<>));
For<Func<Type, IBusinessTransaction>>().Use(type => (IBusinessTransaction)ObjectFactory.GetInstance(type));
});
For<ObjectContext>().Use(() => new ManagementEntities());
}
}
Run Code Online (Sandbox Code Playgroud)
你怎么看?
我希望能够做到以下几点:
Func<int,bool> tryMethodFunc = TryMethod;
Run Code Online (Sandbox Code Playgroud)
TryMethod的签名如下:
bool TryMethod(int value, int value2 = 0, double value3 = 100.0)
Run Code Online (Sandbox Code Playgroud)
我并不反对将方法分解为一种curry格式,但如果没有这种方法可以做到这一点,那将会更有效.
在下面的例子中,我如何轻松转换eventScores
为List<int>
可以将其用作参数prettyPrint
?
Console.WriteLine("Example of LINQ's Where:");
List<int> scores = new List<int> { 1,2,3,4,5,6,7,8 };
var evenScores = scores.Where(i => i % 2 == 0);
Action<List<int>, string> prettyPrint = (list, title) =>
{
Console.WriteLine("*** {0} ***", title);
list.ForEach(i => Console.WriteLine(i));
};
scores.ForEach(i => Console.WriteLine(i));
prettyPrint(scores, "The Scores:");
foreach (int score in evenScores) { Console.WriteLine(score); }
Run Code Online (Sandbox Code Playgroud) 例如,哪一个在方法中的参数类型(与LINQ无关)中更好.显然Func更好,因为它更简单,更具描述性,如果每个人都在使用它,一切都将变得兼容(好).但是我注意到Microsoft在某些库中使用自己的委托,例如事件处理程序.那么,它们中的任何一个的优点和缺点是什么?我应该什么时候使用它?
编辑:
显然Func <>仅在3.5中可用,所以这可能是我看到非Func代表的主要原因.任何其他不使用Func的原因?(例如:这是来自.NET4)
同样的问题也适用于Action <>
对于相当模糊的标题表示道歉,但我想要实现的目标可能在代码中有更好的说明.
我有一个WCF客户端.当我调用方法时,我想将每个调用包装在一些错误处理代码中.因此,我没有直接公开方法,而是在客户端类上创建了以下辅助函数:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
try
{
return serviceMethod(decorator);
}
[...]
}
Run Code Online (Sandbox Code Playgroud)
客户端代码使用它如下:
service.HandleServiceCall(channel => channel.Ping("Hello"));
Run Code Online (Sandbox Code Playgroud)
对Ping的调用很好地包含在一些试图处理任何错误的逻辑中.
这很好用,除了我现在需要知道在服务上实际调用哪些方法.最初,我希望只是检查Func<IApplicationService, T>
使用表达式树,但没有走得太远.
最后,我决定使用Decorator模式:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
var decorator = new ServiceCallDecorator(client.ServiceChannel);
try
{
return serviceMethod(decorator);
}
[...]
finally
{
if (decorator.PingWasCalled)
{
Console.Writeline("I know that Ping was called")
}
}
}
Run Code Online (Sandbox Code Playgroud)
而装饰者本身:
private class ServiceCallDecorator : IApplicationService
{
private readonly IApplicationService service;
public ServiceCallDecorator(IApplicationService service)
{
this.service = service;
this.PingWasCalled = new Nullable<bool>();
}
public …
Run Code Online (Sandbox Code Playgroud) 如果我需要快速可重复使用的代码,我更喜欢使用Action或Func,但是我团队中的其他人不喜欢它们或理解它们.
目前,我唯一真正的论点是关于偏好和更新的代码实践,但这些只是不好的论点.
为什么这样做更好:
Action<FormView,String> hideControl = (form,name) => {
var button = form.GetControl<Button>(name);
if (button != null)
button.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)
比:
public static void HideControl<T>(this FormView form, string name) where T : Control
{
var button = form.GetControl<Button>(name);
if (button != null)
button.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)
?
任何人都可以给我具体的具体论据/例子吗?
我想写一个方法,它做了一些工作,最后返回另一个方法与原始方法相同的签名.这个想法是依次处理一个字节流,而不是进入递归.通过这样称呼它:
MyDelegate executeMethod = handleFirstByte //What form should be MyDelegate?
foreach (Byte myByte in Bytes)
{
executeMethod = executeMethod(myByte); //does stuff on byte and returns the method to handle the following byte
}
Run Code Online (Sandbox Code Playgroud)
要切换方法,我想将它们分配给Func委托.但我遇到的问题是,这导致递归声明而没有终止...
Func<byte, Func<byte, <Func<byte, etc... >>>
Run Code Online (Sandbox Code Playgroud)
我不知何故在这里迷路了.我怎么能绕过那个?
我有一个接口,从Repository模式定义一个存储库:
interface IRepository
{
List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression);
}
Run Code Online (Sandbox Code Playgroud)
我已经针对Entity Framework实现了它:
class EntityFrameworkRepository
{
public List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression)
{
return DBContext.Customers.Where(expression).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎运作良好,它允许我做类似的事情:
var customers = entityFrameworkRepository.Where(
customer => String.IsNullOrEmpty(customer.PhoneNumber)
);
Run Code Online (Sandbox Code Playgroud)
现在我想要一个InMemoryRepository用于测试和演示目的.我试图创建一个:
class InMemoryRepository
{
Dictionary<int, Customer> Customers {get; set;} = new Dictionary<int, Customer>();
public List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression)
{
//what do I put here?
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的那样,我对InMemoryRepository.GetAllCustomers
实现的操作感到困惑.我应该在那里用提供的表达式过滤Customers并返回结果?
我试过了:
return Customers.Where(expression));
Run Code Online (Sandbox Code Playgroud)
但很明显它是期待的,Func<KeyValuePair<int, Customer>, bool>
所以我得到一个编译错误:
错误CS1929'Dictionary'不包含'Where'的定义和最佳扩展方法重载'Queryable.Where(IQueryable,Expression>)'需要类型为'IQueryable'DataAccess.InMemory的接收器
c# ×10
func ×10
.net ×4
delegates ×3
linq ×3
action ×2
c#-4.0 ×1
coding-style ×1
decorator ×1
iqueryable ×1