C# 获取一个无参数方法,使其作用类似于Func<;ReturnT>;

C# 获取一个无参数方法,使其作用类似于Func<;ReturnT>;,c#,lambda,extension-methods,fluent-interface,C#,Lambda,Extension Methods,Fluent Interface,我正在努力使我的代码的一部分更流畅 我有一个字符串扩展,它用字符串发出HTTP请求,并以字符串形式返回响应。所以我可以做一些像 string _html = "http://www.stackoverflow.com".Request(); public static T KeepTrying<T>(this Func<T> KeepTryingThis) { // Code to ignore exceptions and keep trying goes her

我正在努力使我的代码的一部分更流畅

我有一个字符串扩展,它用字符串发出HTTP请求,并以字符串形式返回响应。所以我可以做一些像

string _html = "http://www.stackoverflow.com".Request();
public static T KeepTrying<T>(this Func<T> KeepTryingThis) {
  // Code to ignore exceptions and keep trying goes here
  // Returns the result of KeepTryingThis if it succeeds
}
string _html = "http://www.stackoverflow.com".Request.KeepTrying();
我正在尝试编写一个扩展,它将继续尝试请求,直到成功。我的签名看起来像

string _html = "http://www.stackoverflow.com".Request();
public static T KeepTrying<T>(this Func<T> KeepTryingThis) {
  // Code to ignore exceptions and keep trying goes here
  // Returns the result of KeepTryingThis if it succeeds
}
string _html = "http://www.stackoverflow.com".Request.KeepTrying();
唉,这似乎不起作用。我试着先把它做成一个lambda,但似乎也不起作用

string _html = (() => "http://www.stackoverflow.com".Request()).KeepTrying();
有没有一种方法可以在保持语法相当流畅的同时完成我正在尝试的任务? 非常感谢您的建议


谢谢。

您不能将方法组用于扩展方法或lambda表达式。我

我想你可以投到
Func

或者,如果希望保持
Request
方法本身的简单性,只需添加
RequestFunc
方法:

public static Func<string> RequestFunc(this string url)
{
    return () => url.Request();
}

为什么不把它的头呢

  static T KeepTrying<T>(Func<T> func) {
        T val = default(T);
        while (true) {
            try {
                val = func();
                break;
            } catch { }
        }

        return val;
    }

    var html = KeepTrying(() => "http://www.stackoverflow.com".Request());
static T KeepTrying(Func-Func){
T val=默认值(T);
while(true){
试一试{
val=func();
打破
}捕获{}
}
返回val;
}
var html=KeepTrying(()=>)http://www.stackoverflow.com“.Request());

如何增强请求

string _html = "http://www.stackoverflow.com".Request(RequestOptions.KeepTrying);

string _html = "http://www.stackoverflow.com".Request(RequestOptions.Once);
RequestOptions
是一个枚举。您还可以有更多选项、超时参数、重试次数等


好的,您可以编写一个扩展方法来扩展
Func
委托,但编译器不知道您的意思:

string _html = "http://www.stackoverflow.com".Request.KeepTrying(); // won't work
但如果显式强制转换,则委托将起作用:

string _html = ((Func<string>)"http://www.stackoverflow.com".Request).KeepTrying(); // works
string\u html=((Func)”http://www.stackoverflow.com“.Request).KeepTrying();//作品

这里的问题是,在这种情况下,扩展方法是否真的提高了代码的可读性。

我不会为字符串编写扩展方法。使用更具体的类型,如
Uri

完整代码:

public static class Extensions
{
    public static UriRequest Request(this Uri uri)
    {
        return new UriRequest(uri);
    }

    public static UriRequest KeepTrying(this UriRequest uriRequest)
    {
        uriRequest.KeepTrying = true;
        return uriRequest;
    }
}

public class UriRequest
{
    public Uri Uri { get; set; }
    public bool KeepTrying { get; set; }
    public UriRequest(Uri uri)
    {
        this.Uri = uri;
    }

    public string ToHtml()
    {
        var client = new System.Net.WebClient();

        do
        {
            try
            {
                using (var reader = new StreamReader(client.OpenRead(this.Uri)))
                {
                    return reader.ReadToEnd();
                }
            }
            catch (WebException ex)
            {
                // log ex
            }
        }
        while (KeepTrying);

        return null;
    }

    public static implicit operator string(UriRequest uriRequest)
    {
        return uriRequest.ToHtml();
    }    
}
称之为:

 string html = new Uri("http://www.stackoverflow.com").Request().KeepTrying();

该死-我希望您可以将其编写为var html=KeepTrying(“…”.Request),但方法组和泛型类型推断不能很好地结合在一起:(这将是我的最后一个选项。@sambo99-我想这真的将是我的最后一个选项。因为lambdas很长,所以KeepTrying的结尾用右括号分隔,有时可能会比较难找到。例如KeepTrying(()=>_x.DoSomething().DoMoreStuff()和tensmoreme().plussomeofthistuff())。子字符串(0,5);无论如何,我已经投了赞成票。我将使用Skeet的最后一个建议和一些函数链接助手。@冯,很公平,Jon的建议效果很好。就我个人而言,我喜欢在前面重试一个块,这似乎与foreach更一致,while等等……但是关闭parenthasis有点烦人。作为一种通用方法epTrying可以应用于任何Func,而不仅仅是请求。另外,我的观点是,使用enum会有点不流畅。这很好,只要继续尝试请求不需要特殊处理(例如异常)和附加参数(超时等)。
 string html = new Uri("http://www.stackoverflow.com").Request().KeepTrying();