1.首先我们应该知道什么是扩展方法:
- 定义一个静态类以包含扩展方法。
- 将该扩展方法实现为静态方法,并使其至少具有与包含类相同的可见性。
- 该方法的第一个参数指定方法所操作的类型;该参数必须以 this 修饰符开头。
- 在调用代码中,添加一条 using 指令以指定包含扩展方法类的 命名空间。
- 按照与调用类型上的实例方法一样的方式调用扩展方法。
好了,概念性的问题我们都知道了,如果你还没有理解,我们直接写个简单的实例:
using System; namespace 扩展方法
{
using StringUnit;//添加包含扩展方法类的命名空间
class Program
{
static void Main(string[] args)
{
string s1 = "你好";
string s2 = "rohelm!";
string s3 = "["+s1.StringCombine(s2).StringCombine("]");
Console.WriteLine(s3);
string s4 = StringPro.StringQuote(s2);//也可以利用静态方法调用哦
string s5 = s1.StringQuote();
Console.WriteLine(s4.StringCombine(s5));
Console.ReadKey();
}
}
}
namespace StringUnit
{
static class StringPro//定义一个静态类以包含扩展方法
{
public static string StringCombine(this string str1, string str2)//第一个参数必须以 this修饰符开头。
{
return str1 + str2;
}
public static string StringQuote(this string str)
{
return "[" + str + "]";
}
}
}
我们从上面的代码中随意的取出一个进行大概的说明:public static string StringQuote(this string str),第一个参数不是由调用代码指定的,因为它表示正应用运算符的类型,并且编译器已经知道对象的类型。也就是这个扩展方法只适用于string类型的运算,因此当我们在Main方法中
s2.StringQuote
当我们一点的时候StringQuote就会自动奔出来,好像是String类内置的一个方法一样,我们于是可以按照实例方法一样的方式调用扩展方法,当
然我们依然可以使用静态方法一样的方式调用扩展方法例如:StringPro.StringQuote(s2)。这里我们要注意扩展方法和类的static以及this关键字.
好了我们现在写一个大家最简单的匿名方法,知道我要干什么吗?先写出来。。。
class Program
{
static void Main(string[] args)
{
StringDelegate f=delegate(string s1,string s2){
return s1+s2;
};
Console.WriteLine(f("你好","rohelm.X"));
Console.ReadKey();
}
}
delegate string StringDelegate(string s1,string s2);
简单的都不好意思解释,好了现在我们简化匿名函数
StringDelegate f=delegate(string s1,string s2){
return s1+s2;
};
于是乎这句变得非常怪异而简单:
StringDelegate f=(s1,s2)=>{
return s1+s2;
};
这就是使用Linq和lambda表达式得出的结果,为什么我们不在需要指出s1,s2的参数类型呢,你觉得编译器知道他们该是什么类型吗?
当然,这就是因为我们这个匿名函数是由delegate string StringDelegate(string s1,string s2); 这个委托约束的,因此当然不用猜测就知道
s1,s2的数据类型了,这叫类型推断,所以省略了似乎多余的参数类型声明,但是或许对于新手损失可读性,但是他的确非常强大。其实这个例子很简单,就是参数类表的优化而已,后面{}内仍旧是方法体。
话到这里我们开始新手的Linq之旅
LINQ是.NET3.5引入的功能,LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况。
目的:以统一的方式对数据进行操作。
Linq和扩展方法又有什么联系?好了我们看一下一个简单的示例:
1 int [] numbers = new int [7] { 60, 17, 12, 63, 35, 5, 6 };
2 IEnumerable< int > query = numbers.OrderByDescending(i=>i); //按照降序排列
3 foreach ( var i in query)
4 {
5 Console.Write( "{0,3}" ,i);
6 }
7 Console.WriteLine();
8 IEnumerable< int > query1 = numbers.OrderBy(i => i); //按照升序排列
9 foreach ( var i in query1)
10 { 11 Console.Write( "{0,3}" , i);
12 } |
同样我们在numbers后点的时候会出现
就好像是Array内置的的方法一样。
现在我们来看他的函数定义的特点:
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer
)
由此我们就可以断定Linq内的函数都其实是扩展方法。
- 获取数据源。
- 创建查询。
class IntroToLINQ
{
static void Main()
{
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // 2. Query creation.
// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers
where (num % 2) == 0
select num; // 3. Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
}
}
当然没学LinQ我们依然可以老掉牙的这样写:
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
List<int> list = new List<int>();
foreach (int num in numbers)
{
if (num % 2 == 0)
{
list.Add(num);
}
}
foreach (int i in list)
{
Console.Write("{0,1} ", i);
}
现在我们这样,利用lambda表达式简化上面的官方示例,只需改一句即可完成相同的功能:
int[] numbers = new int[7] { 60, 17, 12, 63, 35, 5, 6 };
IEnumerable<int> query = numbers.Where(i=>i%2==0);
同时,官方示例内部实行时其实编译器依旧将其转化为lambda表达式的形式。
linq 的查询语句看起来非常像SQL语句,但是和SQL无关。
现在来简要的介绍一下常用的语句,和同学们一起学习下,我也是刚刚学的,不过了解这些还是皮毛,要深入的要就就要熟练掌握必须花时间去深入研究。
1.查询表达式必须以 from子句开头
- from 子句中引用的数据源的类型必须为 IEnumerable、 IEnumerable < T >或一种派生类型(如 IQueryable <T >)。
- 查询表达式还可以包含子查询,子查询也是以 from 子句开头。
到此我们先熟悉一下这几个查询关键字,做个小测试:
static void Main()
{
string values = "abcdefasfsafcdekjekyursdjdagghiaaefrxfgs";
var query =
from value in values
group value by value into repeatGroup//通过使用into标识符,可以对每个组调用 Count 方法
orderby repeatGroup.Count() descending//降序排列
select new { 字符 = repeatGroup.Key, 次数 = repeatGroup.Count() };
//通过select返回匿名类型对象实现返回多列的效果
foreach (var cha in query)
{
Console.WriteLine(cha.字符 + "=" + cha.次数);
}
Console.ReadKey();
}
刚好发现一个嵌套的form子句的例子,里面使用let子句来保存临时变量,也就是句子拆成单词再返回合适条件的。
1 using System;
2 using System.Linq;
3 class LetSample1
4 {
5 static void Main()
6 {
7 string [] strings =
8 {
9 "A penny saved is a penny earned." ,
10 "The early bird catches the worm." ,
11 "The pen is mightier than the sword."
12 }; 13 14 var earlyBirdQuery =
15 from sentence in strings
16 let words = sentence.Split( ' ' )
17 from word in words
18 let w = word.ToLower()
19 where w[0] == 'a' || w[0] == 'e'
20 || w[0] == 'i' || w[0] == 'o'
21 || w[0] == 'u'
22 select word;
23 24 // Execute the query.
25 foreach ( var v in earlyBirdQuery)
26 { 27 Console.WriteLine( "\"{0}\" starts with a vowel" , v);
28 } 29 30 // Keep the console window open in debug mode.
31 Console.WriteLine( "Press any key to exit." );
32 Console.ReadKey(); 33 } 34 } |
下面的方法都是IEnumerable<T>的扩展方法:
Average计算平均值;
Min最小元素;
Max最大元素;
Sum元素总和;
Count元素数量;
Concat连接两个序列;
Contains序列是否包含指定元素;
Distinct取得序列中的非重复元素;
Except获得两个序列的差集;
Intersect获得两个序列的交集;
First取得序列第一个元素;
Single取得序列的唯一一个元素,如果元素个数不是1个,则报错
FirstOrDefault 取得序列第一个元素,如果没有一个元素,则返回默认值;
Linq只能用于范型的序列,IEnumerable<T>,对于非范型,可以用Cast或者OfType
IEnumerable的方法:
Cast<TResult>:由于Linq要针对范型类型操作,对于老版本.Net类等非范型的IEnumerable序列可以用Cast方法转换为范型的序列。ArrayList l; IEnumerable<int> il = l.Cast<int>();
OfType<TResult>:Cast会尝试将序列中所有元素都转换为TResult类型,如果待转换的非范型序列中含有其他类型,则会报错。OfType则是只将序列中挑出指定类型的元素转换到范型序列中。
Linq对于小数据量、对性能要求不高的环节用linq很方便,而且延迟加载机制降低了内存占用,比一般人写的程序效率都高。
从扩展方法到匿名方法再到LINQ的更多相关文章
-
编写高质量代码改善C#程序的157个建议——建议37:使用Lambda表达式代替方法和匿名方法
建议37:使用Lambda表达式代替方法和匿名方法 在建议36中,我们创建了这样一个实例程序: static void Main(string[] args) { Func<int, int, ...
-
编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]
前言 泛型并不是C#语言一开始就带有的特性,而是在FCL2.0之后实现的新功能.基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用.同时,它减少了泛型类及泛型方法中的转型,确保了类型安全.委托 ...
-
.net学习之新语法学习(匿名类和匿名方法,扩展方法,系统内置委托,Lambda表达式和linq等)
1.自动属性 Auto-Implemented Properties 2.隐式类型 var var变量不能作为全局变量使用,因为不能在编译时确定类型 3.参数默认值 和 命名参数 4.对象初始化器 ...
-
匿名方法,Lambda表达式,高阶函数
原文:匿名方法,Lambda表达式,高阶函数 匿名方法 c#2.0引入匿名方法,不必创建单独的方法,因此减少了所需的编码系统开销. 常用于将委托和匿名方法关联,例如1. 使用委托和方法关联: this ...
-
[C#] C# 基础回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
-
Delphi异步编程:匿名线程与匿名方法
异步编程,是项目中非常有用的而且常用的一种方法,大多以线程实现. 而Delphi传统方法使用线程略为烦琐,好在其后续版本中,提供一些方法,简化一些操作. 几个概念: 匿名线程:TAnonymousTh ...
-
委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结
第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...
-
C# 知识回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
-
委托delegate 泛型委托action<;>; 返回值泛型委托Func<;>; 匿名方法 lambda表达式 的理解
1.使用简单委托 namespace 简单委托 { class Program { //委托方法签名 delegate void MyBookDel(int a); //定义委托 static MyB ...
随机推荐
-
Android 复制文本内容到系统剪贴板的最简单实践
这个例子很简单,直接上截图和代码. 布局文件activity_copy.xml代码如下: <?xml version="1.0" encoding="utf-8&q ...
-
《java JDK7 学习笔记》之接口与多态
1.对于"定义行为"也就是接口,可以使用interface关键字定义,接口中的方法不能操作,直接标示为abstract,而且一定是public修饰的. 类要操作接口,必须使用imp ...
-
编解码-protobuf
Google的Protobuf在业界非常流行,很多商业项目选择Protobuf作为编解码框架,Protobuf的优点. (1)在谷歌内部长期使用,产品成熟度高: (2)跨语言,支持多种语言,包括C++ ...
-
深入JVM系列之(3):JavaCore和HeapDump
jvm 生成javacore和heapdump文件 在Server端开发与运维中,经常需要生成javacore和heapdump文件,以便分析jvm的运行状态.javacore文件中给出jvm线程的详 ...
-
C语言 可变参数
一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ...
-
hdu 3549 Flow Problem
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Description Network flow is a well- ...
-
某项目 需要在UITabbar 上显示小红点,在此搜罗了三个方法。
1.使用系统自带的,并且可以在小红点上显示数字. [itemOne setBadgeValue:@""]; //显示不带数字的小红点 [itemOne setBadgeValue: ...
-
UOJ #278. 【UTR #2】题目排列顺序(排序水题)
#278. [UTR #2]题目排列顺序 丢个传送门:http://uoj.ac/problem/278 描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 U ...
-
Mysql分表:Merge
merge是Mysql最简单的一种分表,Mysql自带的一个分表功能,Merge表并不保存数据,Merge表和分表是对应映射关系.demo: 创建分表:CREATE TABLE `user1` ( ` ...
-
java在进程启动和关闭.exe程序
/** * @desc 启动进程 * @author zp * @date 2018-3-29 */ public static void startProc(String processName) ...