浅析EF涉及的一些C#语言特性
2015-07-02 14:42
603 查看
主题:Entity Framework涉及的一些C#语言特性,要讲的语言特性,如下图所示
下面的例子完成一个计算某个月剩余天数的功能,我们可以如下编码:调用一个静态帮助类的静态方法。
这样写当然没什么问题。很多时候就是这样用的
如果我们用扩展方法,可以如下实现,注意区别在哪里!
下面用扩展方法实现的程序明显比上面的普通函数调用,更容易阅读。
其实,扩展方法也就是C#的一个语法糖衣,其编译过后也是方法的调用,其优点是更容易阅读,因为其可以为一些固有的类如DateTime、String...扩展一些方法。
上面的代码运行当然也木有什么问题,但是实现方法有点繁琐。
可以初步简化如下:
进一步简化:
不喜欢这种写法?可以用LINQ来写,如下:
让我们回到那个扩展方法,从头来实现 ,如下:
程序运行OK。既然传入一个委托调用函数可以,那么直接传入匿名不更简单,如下:
直接用Lambda来简化吧,如下:
--------
大功告成,利用MS的Where背后的这些C#语法特性,实现了一个类似的Where。
等等..........
貌似忘了一个东西,对Func<>/Action<>委托啊,干嘛自己定义?
重新写下,如下:
这下OK了
(x, y) => x * y //多参数,隐式类型=> 表达式
x => x * 5 //单参数, 隐式类型=>表达式
x => { return x * 5; } //单参数,隐式类型=>语句块
(int x) => x * 5 //单参数,显式类型=>表达式
(int x) => { return x * 5; } //单参数,显式类型=>语句块
() => Console.WriteLine() //无参数
上述格式都是Lambda表达式的合法格式,在编写Lambda表达式时,可以忽略参数的类型,因为编译器能够根据上下文直接推断参数的类型。
Func<TObject, bool>是委托(delegate)
Expression<Func<TObject, bool>>是表达式
Expression编译后就会变成delegate,才能运行。比如
Expression<Func<int, bool>> ex = x=>x < 100;
Func<int, bool> func = ex.Compile();
然后你就可以调用func:
func(5) //-返回 true
func(200) //- 返回 false
而表达式是不能直接调用的。
参考:http://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct
关于EF中用哪个你可以看看这篇文章:Entity Framework - Func引起的数据库全表查询
关于如何将多个expression合并为一个可以写多个where:
.where(expression1).where(expression2)...
运行时EF会自动合并优化的
构建一个可枚举的集合,这是新特性,逆变与协变(和“父类可以替换子类”相似)。
2.类似“Where”的语法如何自己构建。
3.Lambda表达式的写法。譬如说{}。
1.Extension Methods
很旧的主题了,DebugLZQ以前也有相关的博文提过。用个简单点的例子来说吧下面的例子完成一个计算某个月剩余天数的功能,我们可以如下编码:调用一个静态帮助类的静态方法。
using System; namespace ExtensionMethods { class Program { static void Main(string[] args) { DateTime dateTime = new DateTime(2013, 3, 22); int daysTillEndOfMonth = DateUtilities.DaysToEndOfMonth(dateTime); Console.WriteLine(daysTillEndOfMonth); Console.ReadKey(); } } public static class DateUtilities { public static int DaysToEndOfMonth(DateTime dateTime) { return DateTime.DaysInMonth(dateTime.Year, dateTime.Month) - dateTime.Day; } } }
这样写当然没什么问题。很多时候就是这样用的
如果我们用扩展方法,可以如下实现,注意区别在哪里!
using System; namespace ExtensionMethods { class Program { static void Main(string[] args) { DateTime dateTime = new DateTime(2013, 3, 22); int daysTillEndOfMonth = dateTime.DaysToEndOfMonth(); Console.WriteLine(daysTillEndOfMonth); Console.ReadKey(); } } public static class DateUtilities { public static int DaysToEndOfMonth(this DateTime dateTime) { return DateTime.DaysInMonth(dateTime.Year, dateTime.Month) - dateTime.Day; } } }
下面用扩展方法实现的程序明显比上面的普通函数调用,更容易阅读。
其实,扩展方法也就是C#的一个语法糖衣,其编译过后也是方法的调用,其优点是更容易阅读,因为其可以为一些固有的类如DateTime、String...扩展一些方法。
2.Query Language
下面通过上面的扩展方法,来实现数据查询。可以实现如下:using System; using System.Collections.Generic; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] {"Suzhou","Wuxi","Changzhou","Zhenjiang","Nanjing","Shanghai"}; IEnumerable<string> query = cities.StringThatStartWith("S"); foreach(var city in query) { Console.WriteLine(city); } Console.ReadKey(); } } //写一个扩展方法用迭代器实现过滤 public static class FilterExtension { public static IEnumerable<string> StringThatStartWith(this IEnumerable<string> input,string start) { foreach(var s in input) { if (s.StartsWith(start)) yield return s; } } } }
上面的代码运行当然也木有什么问题,但是实现方法有点繁琐。
可以初步简化如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] {"Suzhou","Wuxi","Changzhou","Zhenjiang","Nanjing","Shanghai"}; IEnumerable<string> query = cities.StringThatStartWith("S"); foreach(var city in query) { Console.WriteLine(city); } Console.ReadKey(); } } // public static class FilterExtension { public static IEnumerable<string> StringThatStartWith(this IEnumerable<string> input,string start) { return input.Where(s => s.StartsWith(start)); } } }
进一步简化:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] {"Suzhou","Wuxi","Changzhou","Zhenjiang","Nanjing","Shanghai"}; IEnumerable<string> query = cities.Where(s => s.StartsWith("S")); foreach(var city in query) { Console.WriteLine(city); } Console.ReadKey(); } } }
不喜欢这种写法?可以用LINQ来写,如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] {"Suzhou","Wuxi","Changzhou","Zhenjiang","Nanjing","Shanghai"}; //IEnumerable<string> query = cities.Where(s => s.StartsWith("S")); IEnumerable<string> query = from city in cities where city.StartsWith("S") select city; foreach(var city in query) { Console.WriteLine(city); } Console.ReadKey(); } } }
3.Oh,Holy Shit!
Where从哪里冒出来的!盗用了MS的东西!这里:IEnumerable<string> query = cities.Where(s => s.StartsWith("S"));//这个“Where”,MS是怎么做到的?自己定义一个Filter怎么样?
让我们回到那个扩展方法,从头来实现 ,如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" }; IEnumerable<string> query = cities.Filter(StringThatStartWith); foreach (var city in query) { Console.WriteLine(city); } Console.ReadKey(); } static bool StringThatStartWith(string item,string startWord) { return item.StartsWith(startWord); } } //委托作为扩展方法的参数 public static class FilterExtension { public delegate bool FilterDelegate(string item,string startWord); public static IEnumerable<string> Filter(this IEnumerable<string> input, FilterDelegate fDelegate) { foreach (var item in input) { if (fDelegate(item,"S")) yield return item; } } } }
程序运行OK。既然传入一个委托调用函数可以,那么直接传入匿名不更简单,如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" }; //匿名方法简化 IEnumerable<string> query = cities.Filter(delegate(string item,string startWord) { return item.StartsWith(startWord); }); foreach (var city in query) { Console.WriteLine(city); } Console.ReadKey(); } //static bool StringThatStartWith(string item,string startWord) //{ // return item.StartsWith(startWord); //} } //委托作为扩展方法的参数 public static class FilterExtension { public delegate bool FilterDelegate(string item,string startWord); public static IEnumerable<string> Filter(this IEnumerable<string> input, FilterDelegate fDelegate) { foreach (var item in input) { if (fDelegate(item,"S")) yield return item; } } } }
直接用Lambda来简化吧,如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" }; //Lambda //至此实现了同“Where”长相一样的方法! IEnumerable<string> query = cities.Filter((item, startWord) => item.StartsWith(startWord)); foreach (var city in query) { Console.WriteLine(city); } Console.ReadKey(); } //static bool StringThatStartWith(string item,string startWord) //{ // return item.StartsWith(startWord); //} } //委托作为扩展方法的参数 public static class FilterExtension { public delegate bool FilterDelegate(string item,string startWord); public static IEnumerable<string> Filter(this IEnumerable<string> input, FilterDelegate fDelegate) { foreach (var item in input) { if (fDelegate(item,"S")) yield return item; } } } }
--------
大功告成,利用MS的Where背后的这些C#语法特性,实现了一个类似的Where。
等等..........
貌似忘了一个东西,对Func<>/Action<>委托啊,干嘛自己定义?
重新写下,如下:
using System; using System.Collections.Generic; using System.Linq; namespace ExtensionQuery { class Program { static void Main(string[] args) { IEnumerable<string> cities = new[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" }; //Lambda //至此实现了同“Where”长相一样的方法! IEnumerable<string> query = cities.Filter((item, startWord) => item.StartsWith(startWord)); foreach (var city in query) { Console.WriteLine(city); } Console.ReadKey(); } //static bool StringThatStartWith(string item,string startWord) //{ // return item.StartsWith(startWord); //} } //委托作为扩展方法的参数 public static class FilterExtension { //public delegate bool FilterDelegate(string item,string startWord); //用Func<>委托取代自定义的委托 public static IEnumerable<string> Filter(this IEnumerable<string> input, Func<string,string,bool> fDelegate) { return input.Where(item => fDelegate(item,"S")); } } }
这下OK了
4.Lambda Expressions
Lambda表达式可以有多个参数、一个参数,或者没有参数。其参数类型可以隐式或者显式。示例代码如下:(x, y) => x * y //多参数,隐式类型=> 表达式
x => x * 5 //单参数, 隐式类型=>表达式
x => { return x * 5; } //单参数,隐式类型=>语句块
(int x) => x * 5 //单参数,显式类型=>表达式
(int x) => { return x * 5; } //单参数,显式类型=>语句块
() => Console.WriteLine() //无参数
上述格式都是Lambda表达式的合法格式,在编写Lambda表达式时,可以忽略参数的类型,因为编译器能够根据上下文直接推断参数的类型。
5.Func<T>和Expression<T>
这个源自园子里的一个博问,问题如下:Func<TObject, bool>是委托(delegate)
Expression<Func<TObject, bool>>是表达式
Expression编译后就会变成delegate,才能运行。比如
Expression<Func<int, bool>> ex = x=>x < 100;
Func<int, bool> func = ex.Compile();
然后你就可以调用func:
func(5) //-返回 true
func(200) //- 返回 false
而表达式是不能直接调用的。
参考:http://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct
关于EF中用哪个你可以看看这篇文章:Entity Framework - Func引起的数据库全表查询
关于如何将多个expression合并为一个可以写多个where:
.where(expression1).where(expression2)...
运行时EF会自动合并优化的
小结
1.下面两种写法都行IEnumerable<string> cities = new[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" }; //IEnumerable<string> cities = new string[] { "Suzhou", "Wuxi", "Changzhou", "Zhenjiang", "Nanjing", "Shanghai" };//OK also
构建一个可枚举的集合,这是新特性,逆变与协变(和“父类可以替换子类”相似)。
2.类似“Where”的语法如何自己构建。
3.Lambda表达式的写法。譬如说{}。
相关文章推荐
- C# new的用法
- C#获取视频文件的播放时间
- C# 发送电子邮件(含附件)用到的类 system.web.mail
- 在C#主线程和子线程将数据传递给对方如何实现
- C# 概念记忆
- C# 关闭显示器(显示)
- C# Message.msg
- C# Generic(转载)
- [c#][福利]BTTool种子文件修改工具
- C# 你不能调用的问题剪贴板线程
- C#内存释放
- C#软件winform程序安装包制作及卸载程序制作
- c#中跨线程调用windows窗体控件 .我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。
- c#中如何跨线程调用windows窗体控件?
- C#操作Word (2)-- 打开&关闭Word文档
- C#课程设计---猜猜看
- C#RAS加密算法
- c#语言
- C#中实现 子窗体控制调用父窗体成员和控件
- C#可以直接调用的Win32API