如何在另一个函数的参数中执行匿名函数以填充其参数之一?

时间:2018-09-19 16:29:34

标签: c# lambda functional-programming

所以我有这个C#代码:

static void Main(string[] args)
{            
   string @string = "- hello dude! - oh hell yeah hey what's up guy";

   Console.WriteLine(String.Join(".", @string.GetSubstringsIndexes("he")));
   Console.Read();
}

添加扩展“ GetSubstringsIndexes”方法的部分类:

partial class StringExtension
{
    public static int[] GetSubstringsIndexes(this string @string, string substring)
    {
        List<int> indexes = new List<int>(@string.Length / substring.Length);

        int result = @string.IndexOf(substring, 0);
        while (result >= 0)
        {
            indexes.Add(result);
            result = @string.IndexOf(substring, result + substring.Length);
        }

        return indexes.ToArray();
    }
}

我希望它是一个String.Join方法的参数括号中的lambda表达式,而不是调用我编写的函数。

我的意思是,我只想不编写此函数然后再调用它,而是编写一个lambda表达式仅使用一次!

我希望它看起来如何的示例:

static void Main(string[] args)
{            
   string @string = "- hello dude! - oh hell yeah hey what's up guy";

   Console.WriteLine(String.Join(".", () => {List<int> ind = new List<int>()..... AND SO ON...} ));
   Console.Read();
}

实际上,我刚刚(在编写此问题时)意识到,对于这种情况,这是没有必要的,因为我的GetSubStringsIndexes方法太大。但是想象一下它是否短。

请告诉我是否可以做这样的事情,如果可以,请告诉我如何做!

编辑:

我已经做到了,这就是它的样子:

        Console.WriteLine(String.Join(".", ((Func<int[]>)
            ( () => 
            {
                List<int> indx = new List<int>();
                int res = @string.IndexOf("he", 0);
                while (res >= 0)
                {
                    indx.Add(res);
                    res = @string.IndexOf("he", res + "he".Length);
                }
                return indx.ToArray();
            }
            ))()));

4 个答案:

答案 0 :(得分:1)

您在问题中的“改进”。这是使用帮助函数的一种更简洁的方法,只需定义一次即可:

static void Execute<TReturn>(Func<TReturn> func) => func();

然后:

Console.WriteLine(Execute(() => { /* any code here */ }));

这将自动推断委托类型并调用委托。这消除了很多混乱。

通常,我建议您不要使用这种风格。请改用多行代码。

答案 1 :(得分:0)

您想要的东西是不可能的,因为String.join()不接受Func<int[]>Expression<Func<int[]>>

如果您不想编写扩展方法,则可以使用本地函数并调用它。

static void Main(string[] args)
{            
   string @string = "- hello dude! - oh hell yeah hey what's up guy";

   Console.WriteLine(String.Join(".", GetIndexes('he'));
   Console.Read();

   int[] GetIndexes(string substring) {
       var indexes = new List<int>();
       // compute indexes as desired. @string is available here.
       return indexes.ToArray();
   }
}

答案 2 :(得分:0)

一种方法是使用Select语句,在其中捕获要检查的字符及其在字符串中的索引(使用语法:Select((item, index) => ...),然后,子字符串存在于该索引处,返回索引,否则返回-1(从Select语句返回),然后在其后跟随一个Where子句以删除任何-1结果

代码有点长,因为在检查子字符串之前,我们还必须确保我们离字符串的末尾不太近(这会导致另一个三元条件返回-1)。

我确定这可以改善,但这是一个开始:

string @string = "- hello dude! - oh hell yeah hey what's up guy";           

var subString = "he";

Console.WriteLine(string.Join(".", @string.Select((chr, index) =>
    index + subString.Length < @string.Length
        ? @string.Substring(index, subString.Length) == subString
            ? index
            : -1
        : -1)
    .Where(result => result > -1)));

如果由于难以理解(由于多个?:三元表达式)而导致阅读困难,请在每行之前加上注释:

// For each character in the string, grab the character and it's index
Console.WriteLine(string.Join(".", @string.Select((chr, index) =>
    // If we're not too close to the end of the string
    index + subString.Length < @string.Length
        // And the substring exists at this index          
        ? @string.Substring(index, subString.Length) == subString
            // Return this index
            ? index
            // Substring not found here; return -1
            : -1
        // We're too close to end; return -1
        : -1) 
    // Return only the indexes where the substring was found
    .Where(result => result > -1)));

答案 3 :(得分:0)

最终结果:

Console.WriteLine(String.Join(".", ((Func<int[]>)
    ( () => 
    {
        List<int> indx = new List<int>();
        int res = @string.IndexOf("he", 0);
        while (res >= 0)
        {
            indx.Add(res);
            res = @string.IndexOf("he", res + "he".Length);
        }
        return indx.ToArray();
    }
))()));