开放的编程资料库

当前位置:我爱分享网 > C#教程 > 正文

C#函数

C#Func教程展示了如何在C#中使用Func委托。

C#没有普通函数,只有成员函数(又名方法)。方法不是一等公民。一流的函数使我们能够创建漂亮而强大的代码,就像在F#中看到的那样。C#通过使用委托和lambda表达式在某种程度上改善了这一点。Func是一个内置的委托,它带来了一些函数式编程特性,有助于减少代码的冗长。

C#函数

Func是一个内置的通用委托类型。其他包括PredicateActionFunc可以与方法、匿名方法或lambda表达式一起使用。

Func可以包含0到16个输入参数,并且必须有一个返回类型。(Func委托有16个重载。)

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

例如,此委托封装了一个方法,该方法具有两个参数并返回由TResult参数指定的类型的值。

C#Func简单例子

以下示例是C#Func委托的简单演示。

string GetMessage()
{
    return "Hello there!";
}

Func<string> sayHello = GetMessage;
Console.WriteLine(sayHello());

在示例中,我们使用Func委托,它没有参数并返回单个值。

string GetMessage()
{
    return "Hello there!";
}

这是我们在Func委托的帮助下引用的函数。

Func<string> sayHello = GetMessage;

我们通过Func委托引用GetMessage函数。Func帮助我们创建简洁的代码。

Console.WriteLine(sayHello());

我们通过委托调用函数并打印输出。

$ dotnet run
Hello there!

C#函数示例

以下示例使用Func来添加值。

int Sum(int x, int y)
{
    return x + y;
}

Func<int, int, int> add = Sum;

int res = add(150, 10);

Console.WriteLine(res);

我们有一个Sum方法,可以将两个值相加。我们通过Func委托引用该方法。

Func<int, int, int> Add = Sum;

这个Func委托接受两个参数并返回一个值。

$ dotnet run
160

在以下示例中,我们使用具有三个输入参数的委托。

int Sum(int x, int y, int z)
{
    return x + y + z;
}

Func<int, int, int, int> add = Sum;

int res = add(150, 20, 30);

Console.WriteLine(res);

这次我们指的是一个接受三个参数的方法。

$ dotnet run
200 

如果没有内置的Func委托,我们需要声明我们的自定义委托。

int Sum(int x, int y)
{
    return x + y;
}

Add AddTwo = Sum;
int res = AddTwo(150, 10);

Console.WriteLine(res);

delegate int Add(int x, int y);

在此示例中,我们通过自定义委托类型引用Sum方法。

带有lambda表达式的C#Func

C#lambda表达式简化了C#Funcs的创建。Lambda表达式是使用=>lambda声明运算符创建的。

Func<int, int, int> randInt = (n1, n2) => new Random().Next(n1, n2);
Console.WriteLine(randInt(1, 100));

在示例中,我们创建了一个返回随机整数的函数。委托接受随机范围的下限和上限两个值。

C#FuncLinqWhere

许多Linq方法将Func委托作为参数。例如,Where方法根据谓词过滤一系列值。

Func<string, bool> HasThree = str => str.Length == 3;

string[] words = 
{ 
    "sky", "forest", "wood", "cloud", "falcon", "owl" , "ocean", 
    "water", "bow", "tiny", "arc"
};

IEnumerable<string> threeLetterWords = words.Where(HasThree);

foreach (var word in threeLetterWords)
{
    Console.WriteLine(word);
}

在示例中,我们有一个单词数组。在Func委托的帮助下,我们过滤了所有包含三个字母的单词。

Func<string, bool> HasThree = str => str.Length == 3;

我们声明了一个Func变量,并为该变量分配了一个lambda表达式。该方法检查字符串的长度并返回一个布尔值。

IEnumerable<string> threeLetterWords = words.Where(HasThree);

我们根据HasThree方法查询数组并选择字符串。

$ dotnet run
sky
owl
bow
arc

Func委托的C#列表

Func委托可以放入容器中。

var vals = new int[] { 1, 2, 3, 4, 5 };

Func<int, int> square = x => x * x;
Func<int, int> cube = x => x * x * x;
Func<int, int> inc = x => x + 1;

var fns = new List<Func<int, int>> 
{
    inc, square, cube
};

foreach (var fn in fns)
{
    var res = vals.Select(fn);

    Console.WriteLine(string.Join(", ", res));
}

我们将三个Func委托放入一个列表中。我们遍历列表并将每个委托应用于数组。

$ dotnet run 
2, 3, 4, 5, 6
1, 4, 9, 16, 25
1, 8, 27, 64, 125

C#Func过滤器数组

在示例中,我们使用Func来过滤一组用户。

User[] users =
{
  new (1, "John", "London", "2001-04-01"),
  new (2, "Lenny", "New York", "1997-12-11"),
  new (3, "Andrew", "Boston", "1987-02-22"),
  new (4, "Peter", "Prague", "1936-03-24"),
  new (5, "Anna", "Bratislava", "1973-11-18"),
  new (6, "Albert", "Bratislava", "1940-12-11"),
  new (7, "Adam", "Trnava", "1983-12-01"),
  new (8, "Robert", "Bratislava", "1935-05-15"),
  new (9, "Robert", "Prague", "1998-03-14"),
};

var city = "Bratislava";
Func<User, bool> livesIn = e => e.City == city;

var res = users.Where(livesIn);

foreach (var e in res)
{
    Console.WriteLine(e);
}

record User(int id, string Name, string City, string DateOfBirth);

从用户数组中,我们找到了居住在布拉迪斯拉发的用户。

var city = "Bratislava";
Func<User, bool> livesIn = e => e.City == city;

在谓词中,我们测试所有City属性等于city变量的用户对象。

var res = users.Where(livesIn);

我们将livesIn谓词传递给Where方法。

$ dotnet run
User { id = 5, Name = Anna, City = Bratislava, DateOfBirth = 1973-11-18 }
User { id = 6, Name = Albert, City = Bratislava, DateOfBirth = 1940-12-11 }
User { id = 8, Name = Robert, City = Bratislava, DateOfBirth = 1935-05-15 }

C#Func按年龄过滤

我们将按年龄筛选列表。

var users = new List<User>
{
  new (1, "John", "London", "2001-04-01"),
  new (2, "Lenny", "New York", "1997-12-11"),
  new (3, "Andrew", "Boston", "1987-02-22"),
  new (4, "Peter", "Prague", "1936-03-24"),
  new (5, "Anna", "Bratislava", "1973-11-18"),
  new (6, "Albert", "Bratislava", "1940-12-11"),
  new (7, "Adam", "Trnava", "1983-12-01"),
  new (8, "Robert", "Bratislava", "1935-05-15"),
  new (9, "Robert", "Prague", "1998-03-14"),
};

var age = 60;
Func<User, bool> olderThan = e => GetAge(e) > age;

var res = users.Where(olderThan);

foreach (var e in res)
{
    Console.WriteLine(e);
}

int GetAge(User user)
{    
    var dob = DateTime.Parse(user.DateOfBirth);
    return (int) Math.Floor((DateTime.Now - dob).TotalDays / 365.25D);
}

record User(int id, string Name, string City, string DateOfBirth);

我们获取所有60岁以上的用户。

Func<User, bool> olderThan = e => GetAge(e) > age;

Func定义中,我们使用GetAge方法来判断用户的年龄。

var res = users.Where(olderThan);

olderThan函数与Where一起应用。

int GetAge(User user)
{    
    var dob = DateTime.Parse(user.DateOfBirth);
    return (int) Math.Floor((DateTime.Now - dob).TotalDays / 365.25D);
}

GetAge方法解析出生日期字符串并计算当前年龄。

$ dotnet run    
User { id = 4, Name = Peter, City = Prague, DateOfBirth = 1936-03-24 }
User { id = 6, Name = Albert, City = Bratislava, DateOfBirth = 1940-12-11 }
User { id = 8, Name = Robert, City = Bratislava, DateOfBirth = 1935-05-15 }

C#谓词

PredicateFunc的特化。Predicate可以完成的所有事情都可以用Func完成。

谓词表示返回布尔值的单参数函数。

User[] users =
{
  new (1, "John", "London", "2001-04-01"),
  new (2, "Lenny", "New York", "1997-12-11"),
  new (3, "Andrew", "Boston", "1987-02-22"),
  new (4, "Peter", "Prague", "1936-03-24"),
  new (5, "Anna", "Bratislava", "1973-11-18"),
  new (6, "Albert", "Bratislava", "1940-12-11"),
  new (7, "Adam", "Trnava", "1983-12-01"),
  new (8, "Robert", "Bratislava", "1935-05-15"),
  new (9, "Robert", "Prague", "1998-03-14"),
};

var age = 60;
Predicate<User> olderThan = e => GetAge(e) > age;

var res = Array.FindAll(users, olderThan);

foreach (var e in res)
{
    Console.WriteLine(e);
}

int GetAge(User user)
{    
    var dob = DateTime.Parse(user.DateOfBirth);
    return (int) Math.Floor((DateTime.Now - dob).TotalDays / 365.25D);
}

record User(int id, string Name, string City, string DateOfBirth);

我们获取所有60岁以上的用户。

Predicate<User> olderThan = e => GetAge(e) > age;

Predicate中,我们跳过返回值,返回值始终是bool

var res = Array.FindAll(users, olderThan);

Array.FindAll方法检索与指定谓词定义的条件匹配的所有元素。

int GetAge(User user)
{    
    var dob = DateTime.Parse(user.DateOfBirth);
    return (int) Math.Floor((DateTime.Now - dob).TotalDays / 365.25D);
}

GetAge方法解析出生日期字符串并计算当前年龄。

$ dotnet run
User { id = 4, Name = Peter, City = Prague, DateOfBirth = 1936-03-24 }
User { id = 6, Name = Albert, City = Bratislava, DateOfBirth = 1940-12-11 }
User { id = 8, Name = Robert, City = Bratislava, DateOfBirth = 1935-05-15 }

C#将Func作为参数传递

在下一个示例中,我们将Func委托传递给一个方法。

var data = new List<Person>
{
    new ("John Doe", "gardener"),
    new ("Robert Brown", "programmer"),
    new ("Lucia Smith", "teacher"),
    new ("Thomas Neuwirth", "teacher")
};

ShowOutput(data, r => r.Occupation == "teacher");

void ShowOutput(List<Person> list, Func<Person, bool> condition)
{
    var data = list.Where(condition);

    foreach (var person in data)
    {
        Console.WriteLine("{0}, {1}", person.Name, person.Occupation);
    }
}

record Person(string Name, string Occupation);

该示例创建了一个人员列表。ShowOutput方法将Func作为第二个参数。它返回所有教师。

void ShowOutput(List<Person> list, Func<Person, bool> condition)

我们将Func传递给ShowOutput方法。方法不能作为函数参数传递,只能作为委托传递。

$ dotnet run
Lucia Smith, teacher
Thomas Neuwirth, teacher

C#函数组合

我们可以通过链接来组合Funcs

var vals = new int[] { 1, 2, 3, 4, 5 };

Func<int, int> inc = e => e + 1;
Func<int, int> cube = e => e * e * e;

var res = vals.Select(inc).Select(cube);

foreach (var e in res)
{
    Console.WriteLine(e);
}

我们有一个整数数组。我们在数组上应用两个函数。

Func<int, int> inc = e => e + 1;
Func<int, int> cube = e => e * e * e;

一个函数增加元素,另一个函数增加元素。

var res = vals.Select(inc).Select(cube);

我们通过链接Select方法在数组上应用这两个函数。

$ dotnet run 
8
27
64
125
216    

在本文中,我们使用了C#Func委托。

访问C#教程或列出所有C#教程。

未经允许不得转载:我爱分享网 » C#函数

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏