LINQ
<h1 id="为什么要学习linq--使处理数据变得简单">为什么要学习linq:使处理数据变得简单</h1><h2 id="需求">需求:</h2>
<p>统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出出现频率高于两次的单词和其出现的频率</p>
<pre><code>var items = s.Where(c => char.IsLetter(c))//过滤非字母
.Select(c => char.ToLower(c))//大写字母转小写
.GroupBy(c => c)//根据字母分组
.Where(g => g.Count()>2)//过滤掉出现次数<=2
.OrderByDescending(g => g.Count())//按次数排序
.Select(g => new {Char = g.Key, Count = g.Count()})
</code></pre>
<h2 id="委托lambdalinq">委托——>lambda——>LINQ</h2>
<h3 id="委托">委托</h3>
<p>1、委托是指向方法的类型,调用委托变量时执行的就是变量指向的方法<br>
2、.NET中定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托</p>
<h4 id="demo-自定义-委托">Demo 自定义 委托</h4>
<h5 id="不带返回值的委托">不带返回值的委托</h5>
<p>** delegate void d(); **</p>
<pre><code>namespace 委托
{
delegate void d();
internal class Program
{
static void Main(string[] args)
{
d d1 = F1;
d1();
}
public static void F1()
{
Console.WriteLine("我是F1");
}
public static void F2()
{
Console.WriteLine("我是F2");
}
}
}
</code></pre>
<p>输出为:<br>
我是F1</p>
<pre><code>namespace 委托
{
delegate void d();
internal class Program
{
static void Main(string[] args)
{
d d1 = F1;
d1();
d1 = F2;
d1();
}
public static void F1()
{
Console.WriteLine("我是F1");
}
public static void F2()
{
Console.WriteLine("我是F2");
}
}
}
</code></pre>
<p>输出:<br>
我是F1<br>
我是F2</p>
<h5 id="带返回值">带返回值</h5>
<pre><code>namespace 委托
{
delegate void d();
delegate int b(int i,int j );
internal class Program
{
static void Main(string[] args)
{
d d1 = F1;
d1();
d1 = F2;
d1();
b b1 = F3;
b1(3, 5);
}
public static void F1()
{
Console.WriteLine("我是F1");
}
public static void F2()
{
Console.WriteLine("我是F2");
}
public static int F3(int a ,int b)
{
Console.WriteLine($"{a+b}");
return a;
}
}
}
</code></pre>
<p>输出<br>
我是F1<br>
我是F2<br>
8</p>
<h3 id="lambda是怎么来的">Lambda是怎么来的</h3>
<h4 id="demo">Demo</h4>
<h5 id="没有参数没有返回值的匿名方法">没有参数没有返回值的匿名方法</h5>
<pre><code>namespace 委托
{
internal class Program
{
static void Main(string[] args)
{
Action f1 = delegate ()
{
Console.WriteLine("我是AAA");
};
f1();
}
}
}
</code></pre>
<p>输出:<br>
我是AAA</p>
<h5 id="带参数的匿名函数">带参数的匿名函数</h5>
<pre><code>namespace 委托
{
internal class Program
{
static void Main(string[] args)
{
Action f1 = delegate ()
{
Console.WriteLine("我是AAA");
};
f1();
Action<int,int> f2 = delegate (int i, int j)
{
Console.WriteLine($"i ={i},j={j}");
};
f2(1,2);
}
}
}
</code></pre>
<p>输出:<br>
我是AAA<br>
i =1,j=2</p>
<h5 id="带参数带返回值的匿名函数">带参数带返回值的匿名函数</h5>
<pre><code>namespace 委托
{
internal class Program
{
static void Main(string[] args)
{
Action f1 = delegate ()
{
Console.WriteLine("我是AAA");
};
f1();
Action<int,int> f2 = delegate (int i, int j)
{
Console.WriteLine($"i ={i},j={j}");
};
f2(1,2);
Func<int, int, int> f3 = delegate (int i, int j)
{
return i + j;
};
Console.WriteLine(f3(1, 2));
}
}
}
</code></pre>
<p>输出<br>
我是AAA<br>
i =1,j=2<br>
3</p>
<h4 id="进入主题-lambda表达式">进入主题 Lambda表达式</h4>
<p>匿名方法可以写出lambda表达式<br>
Func<int,int,string> f1 = (i1,i2)=>{<br>
return $"{i1}+{i2}={i1+i2}";<br>
};<br>
可以省略参数数据类型,因为编译能根据委托类型推断出参数的类型,用=>引出来方法体</p>
<h4 id="demo-1">Demo</h4>
<pre><code>namespace 委托
{
internal class Program
{
static void Main(string[] args)
{
Action f1 = delegate ()
{
Console.WriteLine("我是AAA");
};
f1();
Action<int,int> f2 = delegate (int i, int j)
{
Console.WriteLine($"i ={i},j={j}");
};
f2(1,2);
Func<int, int, int> f3 = delegate (int i, int j)
{
return i + j;
};
Console.WriteLine(f3(1, 2));
Func<int,int,int> f4 = (int i,int j)=> { return i + j; };
Console.WriteLine(f4(1,2));
}
}
}
</code></pre>
<p>这里f3和f4的输出是一样的所以<br>
可以把delegate 换成 => (“=>” 读作goes to)<br>
在上面的例子中还可以省略参数的数据类型,因为编译器可以推断<br>
即</p>
<pre><code> Func<int, int, int> f5 = (i,j) => { return i + j; };
Console.WriteLine(f5(1, 2));
</code></pre>
<blockquote>
<p>如果委托没有返回值且方法体只有一行代码,可以省略{}</p>
</blockquote>
<pre><code> Action f1 = delegate ()
{
Console.WriteLine("我是AAA");
};
f1();
Action f11 =() => Console.WriteLine("我是AAA");
Action<int,int> f2 = delegate (int i, int j)
{
Console.WriteLine($"i ={i},j={j}");
};
f2(1,2);
Action <int,int> f22 = (int i, int j) => Console.WriteLine($"i ={i},j={j}");
</code></pre>
<blockquote>
<p>如果=> 后的方法体中只有一行代码,且方法体有返回值,可以省略方法体的{}和return</p>
</blockquote>
<pre><code> Func<int, int, int> f5 = (i,j) => { return i + j; };
Console.WriteLine(f5(1, 2));
Func<int, int, int> f6 = (i, j) =>i + j;
Console.WriteLine(f5(1, 2));
</code></pre>
<blockquote>
<p>如果只有一个参数,参数的()可以省略</p>
</blockquote>
<h4 id="还原下面的lambda表达式">还原下面的Lambda表达式</h4>
<pre><code>Action<string> f7 = s => Console.WriteLine(s);
</code></pre>
<pre><code>Action<string> f77 = (string s) => { Console.WriteLine(s); };
</code></pre>
<h4 id="简化下面的式子">简化下面的式子</h4>
<pre><code>Func<int, bool> f8 = delegate (int i)
{
return i > 0;
};
</code></pre>
<pre><code>Func<int, bool> f88 = i => i > 0;
</code></pre>
<p>写到这,感慨下语法糖真的是太甜了 🤐</p>
<h2 id="揭秘linq方法的背后-简化数据处理">揭秘LINQ方法的背后 ——简化数据处理</h2>
<h3 id="入门案例">入门案例:</h3>
<blockquote>
<p>对于int[] nums = new [] {1,2,3,2,1,23,25} 打印大于10</p>
</blockquote>
<pre><code>namespace Linq
{
internal class Program
{
static void Main(string[] args)
{
//对于int[] nums = new [] {1,2,3,2,1,23,25} 打印大于10
int[] nums = new[] { 1, 2, 3, 2, 1, 23, 25 };
//法1
foreach (var item in nums)
{
if(item > 10)
{
Console.WriteLine(item);
}
}
//法2
var nums2 = nums.Where(x => x > 10).ToArray();
foreach (var item in nums2)
{
Console.WriteLine(item);
}
}
}
}
</code></pre>
<h4 id="自己实现一个where方法">自己实现一个where方法</h4>
<pre><code> static IEnumerable<int> MyWhere(IEnumerable<int> items,Func<int,bool> f)
{
List<int> result = new List<int>();
foreach (var item in items)
{
if(f(item))
{
result.Add(item);
}
}
return result;
}
</code></pre>
<p>那么上述题目就还有一种实现方法</p>
<pre><code>//法3
var num3 = MyWhere(nums, a => a > 10);
foreach (var item in num3)
{
Console.WriteLine(item);
}
</code></pre>
<h4 id="使用yieid">使用yieId</h4>
<pre><code>static IEnumerable<int> MyWhere(IEnumerable<int> items,Func<int,bool> f)
{
foreach (var item in items)
{
if(f(item))
{
yield return item;
}
}
}
</code></pre>
<blockquote>
<p>yieId : 满足条件的数据立即返回,继续处理下一条,数据处理的效率高</p>
</blockquote>
<h2 id="linq中常用的扩展方法">Linq中常用的扩展方法</h2>
<blockquote>
<p>在System.Linq命名空间中</p>
</blockquote>
<h3 id="准备初始数据">准备初始数据</h3>
<pre><code>public class Employee
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salary { get; set; }
public override string ToString()
{
return $"Id = {Id},Name = {Name}, Age = {Age}, Gender = {Gender} ,Salary = {Salary}";
}
}
</code></pre>
<pre><code> static void Main(string[] args)
{
List<Employee> list = new List<Employee>();
list.Add(new Employee { Id = 1001, Name = "刘磊", Age = 51, Gender = false, Salary = 9797 });
list.Add(new Employee { Id = 1002, Name = "11", Age = 16, Gender = true, Salary = 13968 }); list.Add(new Employee { Id = 1001, Name = "刘1", Age = 21, Gender = false, Salary = 9737 });
list.Add(new Employee { Id = 1002, Name = "21", Age = 49, Gender = true, Salary = 3968 }); list.Add(new Employee { Id = 1001, Name = "刘2磊", Age = 51, Gender = false, Salary = 4757 });
list.Add(new Employee { Id = 1002, Name = "131", Age = 16, Gender = true, Salary = 8968 }); list.Add(new Employee { Id = 1001, Name = "刘3磊", Age = 91, Gender = false, Salary = 8797 });
list.Add(new Employee { Id = 1002, Name = "31", Age = 26, Gender = true, Salary = 6968 }); list.Add(new Employee { Id = 1001, Name = "刘4磊", Age = 81, Gender = false, Salary = 5797 });
list.Add(new Employee { Id = 1002, Name = "刘芳", Age = 36, Gender = true, Salary = 5968 }); list.Add(new Employee { Id = 1001, Name = "刘5磊", Age = 11, Gender = false, Salary = 9777 });
list.Add(new Employee { Id = 1002, Name = "周勇", Age = 74, Gender = true, Salary = 6968 }); list.Add(new Employee { Id = 1001, Name = "刘6磊", Age = 15, Gender = false, Salary = 7897 });
list.Add(new Employee { Id = 1002, Name = "刘涛", Age = 46, Gender = true, Salary = 6968 }); list.Add(new Employee { Id = 1001, Name = "刘7磊", Age = 18, Gender = false, Salary = 5497 });
list.Add(new Employee { Id = 1002, Name = "周勇", Age = 56, Gender = true, Salary = 6968 }); list.Add(new Employee { Id = 1001, Name = "刘8磊", Age = 51, Gender = false, Salary = 5457 });
list.Add(new Employee { Id = 1002, Name = "李伟", Age = 44, Gender = true, Salary = 1368 });
}
</code></pre>
<h3 id="常用扩展方法">常用扩展方法</h3>
<h4 id="where">Where:</h4>
<blockquote>
<p>每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true ,那么这个元素就会放到返回值中<br>
where参数是一个lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非叫e,不过一般lambda表达式中的变量名长度都不长</p>
</blockquote>
<h5 id="输出上面年龄大于30的">输出上面年龄大于30的</h5>
<pre><code>#region Where
list.Where(x => x.Age > 30).ToList().ForEach(x => Console.WriteLine(x));
#endregion
</code></pre>
<h4 id="count">Count:</h4>
<blockquote>
<p>获取数据条数</p>
</blockquote>
<pre><code>#region Count
var count = list.Count(x => x.Age > 30);
Console.WriteLine(count);
#endregion
</code></pre>
<p>如果用的是上述数据的话输出应该是11</p>
<h4 id="any">Any</h4>
<blockquote>
<p>是否至少有一条数据</p>
</blockquote>
<pre><code> #region Any
//是否有名字叫张三的如果有返回true,没有返回false
var isExist = list.Any(x => x.Name == "张三");
Console.WriteLine(isExist);
#endregion
</code></pre>
<p>输出false</p>
<h4 id="获取一条数据是否带参数的两种写法">获取一条数据(是否带参数的两种写法)</h4>
<h5 id="single">Single</h5>
<blockquote>
<p>有且只有一条满足要求的数据<br>
只能筛选一条数据,如果筛选的数据多余一条就会报错(System.InvalidOperationException:“Sequence contains more than one element”),如果没有符合条件的也会报错</p>
</blockquote>
<h6 id="筛选的数据多于1条">筛选的数据多于1条</h6>
<pre><code>#region Single
Console.WriteLine(list.Single());
#endregion
</code></pre>
<p>输出异常:System.InvalidOperationException:“Sequence contains more than one element”</p>
<h6 id="筛选的数据刚好1条">筛选的数据刚好1条</h6>
<pre><code>Console.WriteLine(list.Where(x => x.Name == "11").Single());
</code></pre>
<p>输出对象</p>
<blockquote>
<p>Id = 1002,Name = 11, Age = 16, Gender = True ,Salary = 13968</p>
</blockquote>
<p>上述的写法还可以写成下面的</p>
<pre><code>#region Single
Console.WriteLine(list.Where(x => x.Name == "11").Single());
Console.WriteLine(list.Single(x => x.Name == "11"));
#endregion
</code></pre>
<h6 id="筛选的数据少于一条">筛选的数据少于一条</h6>
<pre><code> #region Single
Console.WriteLine(list.Where(x => x.Name == "张三").Single());
#endregion
</code></pre>
<p>输出异常:System.InvalidOperationException:“Sequence contains no elements”</p>
<blockquote>
<p>结合skip</p>
</blockquote>
<h5 id="singleordefault">SingleOrDefault</h5>
<blockquote>
<p>最多只有一条满足要求的数据</p>
</blockquote>
<h6 id="筛选的数据多于1条-1">筛选的数据多于1条</h6>
<pre><code> #region SingleOrDefault
int[] nums33 = new int[] { 1, 2, 4 };
int i = nums33.SingleOrDefault(i => i > 0);
Console.WriteLine(i);
#endregion
</code></pre>
<p>输出异常:System.InvalidOperationException:“Sequence contains more than one matching element”</p>
<h6 id="筛选的数据等于一条">筛选的数据等于一条</h6>
<pre><code>#region SingleOrDefault
int[] nums33 = new int[] { 1, 2, 4 };
int i = nums33.SingleOrDefault(i => i > 3);
Console.WriteLine(i);
#endregion
</code></pre>
<p>输出4</p>
<h6 id="筛选的数据小于一条">筛选的数据小于一条</h6>
<p><mark>输出0不会报错</mark></p>
<h5 id="first">First</h5>
<blockquote>
<p>至少有一条,返回第一条</p>
</blockquote>
<p>如果一个都没有就报错</p>
<h5 id="firstordefault">FirstOrDefault</h5>
<blockquote>
<p>返回第一条或者默认值</p>
</blockquote>
<blockquote>
<p>防御性编程:选择合适的方法</p>
</blockquote>
<h4 id="排序">排序</h4>
<h5 id="orderby">OrderBy</h5>
<blockquote>
<p>对数据正序排序</p>
</blockquote>
<h5 id="orderbydescending">OrderByDescending</h5>
<blockquote>
<p>倒序排序</p>
</blockquote>
<h5 id="随机排序">随机排序</h5>
<pre><code>
#region 随机排序
var random = list.OrderBy(x => Guid.NewGuid());
random.ToList().ForEach(x => Console.WriteLine(x));
#endregion
</code></pre>
<h5 id="混合条件排序thenby">混合条件排序(ThenBy)</h5>
<p>按年龄排序,如果年龄一样再按工资排序</p>
<pre><code> #region 按年龄排序,如果年龄一样再按工资排序
var em = list.OrderBy(e => e.Age).ThenBy(x => x.Salary);
em.ToList().ForEach(x => Console.WriteLine(x));
#endregion
</code></pre>
<h4 id="限制结果集">限制结果集</h4>
<h5 id="skipn">Skip(n)</h5>
<blockquote>
<p>跳过n条数据</p>
</blockquote>
<h5 id="taken">Take(n)</h5>
<blockquote>
<p>获取n条数据</p>
</blockquote>
<h6 id="demo-2">Demo</h6>
<h6 id="跳过前两条数据取三条">跳过前两条数据取三条</h6>
<pre><code> #region Skip and Take 跳过前两条数据取三条
var list2 = list.Skip(2).Take(3);
list2.ToList().ForEach(x => Console.WriteLine(x));
#endregion
</code></pre>
<h6 id="取出年龄大于30的第2条和第3条">取出年龄大于30的第2条和第3条</h6>
<pre><code> #region 取出年龄大于30的第2条和第3条
var list3 = list.Where(x => x.Age > 30).OrderBy(x => x.Age).Skip(1).Take(2);
list3.ToList().ForEach(x => Console.WriteLine(x));
#endregion
</code></pre>
<h4 id="聚合函数">聚合函数</h4>
<blockquote>
<p>LINQ 中所有的扩展方法几乎都是针对IEnumerable接口的,而几乎所有能返回集合的都返回IEnumerable,所以几乎所有的方法都支持链式调用</p>
</blockquote>
<h5 id="max">Max()</h5>
<blockquote>
<p>最大值</p>
</blockquote>
<h5 id="min">Min()</h5>
<blockquote>
<p>最小值</p>
</blockquote>
<h5 id="average">Average()</h5>
<blockquote>
<p>平均值</p>
</blockquote>
<h5 id="sum">Sum()</h5>
<blockquote>
<p>和</p>
</blockquote>
<pre><code> #region 聚合函数Max Min Average Sum
var max = list.Max(x => x.Age);
Console.WriteLine(max);
var min = list.Min(x => x.Age);
Console.WriteLine(min);
var avg = list.Average(x => x.Age);
Console.WriteLine(avg);
var sum = list.Sum(x => x.Age);
Console.WriteLine(sum);
#endregion
</code></pre>
<h4 id="分组">分组</h4>
<p>GroupBy()方法的参数是分组条件表达式,返回值为IGrouping<TKey,TSource>类型的泛型IEnumerable,也就是每一组以一个IGrouping对象的形式返回,IGrouping是一个继承自IEnumerable的接口,IGrouping中的Key属性表示这一组的分组数据的值</p>
<h5 id="demo-根据年龄分组获取最大最小平均">Demo 根据年龄分组,获取最大,最小,平均</h5>
<pre><code> #region GroupBy根据年龄分组,获取最大工资,最小工资,平均工资
var groupS = list.GroupBy(x => x.Age);
foreach (var item in groupS)
{
Console.WriteLine(item.Key);
Console.WriteLine($"最大工资为:{item.Max(x => x.Salary)}");
Console.WriteLine($"最小工资为:{item.Min(x => x.Salary)}");
Console.WriteLine($"平均工资为:{item.Average(x => x.Salary)}");
foreach (var item2 in item)
{
Console.WriteLine(item2);
}
Console.WriteLine("*******************");
}
#endregion
</code></pre>
<h4 id="投影">投影</h4>
<blockquote>
<p>把集合中的每一项转换为另外一种类型</p>
</blockquote>
<h5 id="select">Select()</h5>
<pre><code> #region 投影 Select
var select = list.Select(x => x.Name);
foreach (var item in select)
{
Console.WriteLine(item);
}
#endregion
</code></pre>
<h4 id="匿名类型">匿名类型</h4>
<pre><code> #region 匿名类型
var obj = new { Name = "张三", Age = 18 };
Console.WriteLine(obj.Name);
#endregion
</code></pre>
<h4 id="投影和匿名类型">投影和匿名类型</h4>
<pre><code> #region 投影和匿名类型
var object1 = list.Select(x => new { 姓名 = x.Name, 年龄 = x.Age });
foreach (var item in object1)
{
Console.WriteLine(item.姓名 + " " + item.年龄);
}
#endregion
</code></pre>
<h2 id="集合转换">集合转换</h2>
<pre><code> #region 集合转换
var ee = list.Where(x => x.Salary > 10000);
var list4 = ee.ToList();
foreach (var item in list4)
{
Console.WriteLine(item);
}
#endregion
</code></pre>
<h3 id="链式调用">链式调用</h3>
<h4 id="demo-获取id1的数据然后按age分组并且按照age排序然后取出前3条再投影获得年龄人数平均工资">Demo 获取id>1的数据然后按Age分组,并且按照Age排序然后取出前3条再投影获得年龄人数,平均工资</h4>
<pre><code> #region获取id>1的数据然后按Age分组,并且按照Age排序然后取出前3条再投影获得年龄人数,平均工资
var result = list.Where(x => x.Id > 1).GroupBy(x => x.Age).Take(3).Select(x => new { 年龄 = x.Key, 人数 = x.Count(), 平均工资 = x.Average(x => x.Salary) });
foreach (var item in result)
{
Console.WriteLine(item.年龄 + " " + item.人数 + " " + item.平均工资);
}
Console.WriteLine("_______________________________________________________________________________________________________________________________");
#endregion
</code></pre>
<h2 id="查询语法">查询语法</h2>
<h3 id="demo-获取工资大于3000的按年龄排序">Demo 获取工资大于3000的按年龄排序</h3>
<pre><code> #region 查询语法 获取工资大于3000的按年龄排序
var li = from s in list
where s.Salary > 3000
select new { s.Name, s.Age, xb = s.Gender ? "男" : "女" };
foreach (var item in li)
{
Console.WriteLine(item);
}
#endregion
</code></pre>
<blockquote>
<p>查询语法和上面的linq运行时没有区别,反编译后是一样的</p>
</blockquote>
<h2 id="linq-解决面试问题">Linq 解决面试问题</h2>
<blockquote>
<p>算法题尽量避免使用正则表达式,Linq这些高级的类库,尽量使用基础的语法 为了更好的性能</p>
</blockquote>
<h3 id="题1--求-263-的最大值">题1求 2,6,3 的最大值</h3>
<pre><code> #region 求 2,6,3 的最大值
int a = 2;
int b = 6;
int c = 3;
//法1;
int[] nums = new [] { 2, 6, 3 };
Console.WriteLine(nums.Max());
//法2
Console.WriteLine(Math.Max(a, Math.Max(b, c)));
//法3
Console.WriteLine(a > b ? (a > c ? a : c) : (b > c ? b : c));
#endregion
</code></pre>
<h3 id="题2-有个用逗号分隔的表示成绩的字符串如619010099182238668093555089计算这些成绩的平均值">题2 有个用逗号分隔的表示成绩的字符串,如:“61,90,100,99,18,22,38,66,80,93,55,50,89”计算这些成绩的平均值</h3>
<pre><code> #region 题2 有个用逗号分隔的表示成绩的字符串,如:“61,90,100,99,18,22,38,66,80,93,55,50,89”计算这些成绩的平均值
//法1
int[] num1s = new[] { 61, 90,100,99,18,22,38,66,80,93,55,50,89 };
Console.WriteLine(num1s.Average());
//法2:
string str = "61,90,100,99,18,22,38,66,80,93,55,50,89";
string[] strs = str.Split(',');
var nums2 = strs.Select(x => int.Parse(x)).ToArray();
var avg2 = nums2.Average();
Console.WriteLine(avg2);
#endregion
</code></pre>
<h3 id="题3统计一个字符串中每个字母出现的频率忽略大小写然后按照从高到低的顺序输出出现频率高于2次的单词和其出现的频率">题3:统计一个字符串中每个字母出现的频率(忽略大小写)然后按照从高到低的顺序输出出现频率高于2次的单词和其出现的频率</h3>
<pre><code> #region 题3: 统计一个字符串中每个字母出现的频率(忽略大小写)然后按照从高到低的顺序输出出现频率高于2次的单词和其出现的频率
string str1 = "Hello World hahaha heiheihei";
var str2 =str1.Where(c => char.IsLetter(c)).Select(c => char.ToLower(c)).GroupBy(c=>c).Select(c => new {c,count = c.Count() }).OrderByDescending(c => c.count).Where(c =>c.count>2);
foreach (var item in str2)
{
Console.WriteLine(item);
}
#endregion
</code></pre><br><br>
来源:https://www.cnblogs.com/nanfengovo/p/18921538
頁:
[1]