有关c#和Linq的一些学习记录

项目里大神的封装用惯了都不知道c#本身还有哪些好玩的写法,今天写了些东西查了一路稍微记录下。

default(T)

无法更改,null for reference types and zero for value types.

无法new T()

1
2
3
if (typeof(T).GetConstructor(Type.EmptyTypes) != null) {
return (T) Activator.CreateInstance(typeof(T));
}

Enumerable

IEnumerator

迭代器 这篇详解帮助理解很不错->C# IEnumerator的详解
尤其是2.2的流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Program
{
static readonly String Padding = new String(' ', 30);
static IEnumerable<Int32> CreateEnumerable()
{
Console.WriteLine("{0} CreateEnumerable()方法开始", Padding);
for (int i = 0; i < 3; i++)
{
Console.WriteLine("{0}开始 yield {1}", i);
yield return i;
Console.WriteLine("{0}yield 结束", Padding);
}
Console.WriteLine("{0} Yielding最后一个值", Padding);
yield return -1;
Console.WriteLine("{0} CreateEnumerable()方法结束", Padding);
}

static void Main(string[] args)
{
IEnumerable<Int32> iterable = CreateEnumerable();
IEnumerator<Int32> iterator = iterable.GetEnumerator();
Console.WriteLine("开始迭代");
while (true)
{
Console.WriteLine("调用MoveNext方法……");
Boolean result = iterator.MoveNext();
Console.WriteLine("MoveNext方法返回的{0}", result);
if (!result)
{
break;
}
Console.WriteLine("获取当前值……");
Console.WriteLine("获取到的当前值为{0}", iterator.Current);
}
Console.ReadKey();
}
}

image

后面记录一些之前不常用到的接口用法
enumerable官方文档->https://msdn.microsoft.com/zh-cn/library/system.linq.enumerable.aspx

GroupBy

1
2
3
4
5
public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Uses method-based query syntax.
// Group the pets using Age as the key value
// and selecting only the pet's Name for each value.
IEnumerable<IGrouping<int, string>> query =
pets.GroupBy(pet => pet.Age, pet => pet.Name);

// Iterate over each IGrouping in the collection.
foreach (IGrouping<int, string> petGroup in query)
{
// Print the key value of the IGrouping.
Console.WriteLine(petGroup.Key);
// Iterate over each value in the
// IGrouping and print the value.
foreach (string name in petGroup)
Console.WriteLine(" {0}", name);
}
1
2
3
4
5
public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, IEnumerable<TSource>, TResult> resultSelector
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Group Pet objects by the Math.Floor of their age.
// Then project an anonymous type from each group
// that consists of the key, the count of the group's
// elements, and the minimum and maximum age in the group.
var query = petsList.GroupBy(
pet => Math.Floor(pet.Age),
(age, pets) => new
{
Key = age,
Count = pets.Count(),
Min = pets.Min(pet => pet.Age),
Max = pets.Max(pet => pet.Age)
});

// Iterate over each anonymous type.
foreach (var result in query)
{
Console.WriteLine("\nAge group: " + result.Key);
Console.WriteLine("Number of pets in this age group: " + result.Count);
Console.WriteLine("Minimum age: " + result.Min);
Console.WriteLine("Maximum age: " + result.Max);
}
1
2
3
4
5
6
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Group Pet.Age values by the Math.Floor of the age.
// Then project an anonymous type from each group
// that consists of the key, the count of the group's
// elements, and the minimum and maximum age in the group.
var query = petsList.GroupBy(
pet => Math.Floor(pet.Age),
pet => pet.Age,
(baseAge, ages) => new
{
Key = baseAge,
Count = ages.Count(),
Min = ages.Min(),
Max = ages.Max()
});
1
2
3
4
var results = persons.GroupBy(
p => p.PersonId,
p => p.car,
(key, g) => new { PersonId = key, Cars = g.ToList() });

Aggregate

1
2
3
4
public static TSource Aggregate<TSource>(
this IEnumerable<TSource> source,
Func<TSource, TSource, TSource> func
)
1
2
3
4
5
6
7
8
string sentence = "the quick brown fox jumps over the lazy dog";

string[] words = sentence.Split(' ');

string reversed = words.Aggregate((workingSentence, next) =>
next + " " + workingSentence);

// dog lazy the over jumps fox brown quick the
1
2
3
4
5
public static TAccumulate Aggregate<TSource, TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func
)
1
2
3
4
5
6
7
int[] ints = { 4, 8, 8, 3, 9, 0, 7, 8, 2 };

// Count the even numbers in the array, using a seed value of 0.
int numEven = ints.Aggregate(0, (total, next) =>
next % 2 == 0 ? total + 1 : total);

// The number of even integers is: 6
1
2
3
4
5
6
public static TResult Aggregate<TSource, TAccumulate, TResult>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate, TSource, TAccumulate> func,
Func<TAccumulate, TResult> resultSelector
)
1
2
3
4
5
6
7
8
9
10
11
string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };

// Determine whether any string in the array is longer than "banana".
string longestName =
fruits.Aggregate("banana",
(longest, next) =>
next.Length > longest.Length ? next : longest,
// Return the final result as an upper case string.
fruit => fruit.ToUpper());

// PASSIONFRUIT

一些常见名词/接口命名

  • Aggregate / Reduce -> 一个序列变成一个值
  • Map -> 一个序列变成另一个等长序列 (在List类里叫ConvertAll)
  • mapreduce
    -> hadoop里指一个分布式计算系统
    -> MongoDB里指 一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。

所以若是设计一个队列类,大概会有这些方法吧

  • Add
  • Concat
  • Merge
  • Remove
  • Contains
  • Aggregate
  • Map
  • Sort
  • Clone
  • Rand
  • Find
  • FirstMatch
  • All
  • Any
  • Sub