.NET语言的SQL化以及Javascript化
引言
上个月,C9校长拜访华为,任正非:光刻机这事你们别管,并直指问题的关键,任正非说,大学的任务是把基础科学做好,不能哪里热搞哪里,光刻机,化学制剂,工艺制程深层次是物理、化学问题,更直白的说是基础科学问题(如材料分子学等)。 如果基础学科学不好,而是哪里热搞哪里,那么你就永远劳于应付。
相信大家也都记得去年日韩矛盾时,日本政府针对韩国的半导体材料出口管制,其中就包含了光刻胶、氟化氢和氟聚酰亚胺三个品种。而日本之所以有这么大的实力敢制裁韩国的巨无霸三星和海力士,最根本的,日本是基础学科做的最好的国家。据说日本在氢氟酸的提纯度已经达到99.9999999999%甚至更高,其他公司无法替代。
Part1
计算机编程基础
记得我再学习计算机课程时,当时老师说,计算机基本上只有三个语法:顺序,判断和循环,至于跳转已经破坏流程的严谨性,最好少用。 这种观点类似中国的“一生二,二生三,三生万物”一样。只要掌握这三种基础,那么你遇到问题,都能轻易解决。好吧,具个例子:
如果今天下雨或者下雪,那么我就带雨伞
如果转换为计算机语言,写成if语句
if ((today=="下雨" )|| if (today=="下雪")) { console.write("带雨伞"); } else { //Do Noting }
计算机Web的基础
计算机Web的基础是什么?是Http请求和响应。不论你学习的是ASP, ASP.NET, JSP,PHP等,不管你用的那种语言,都必须了解,Web的请求是Request和Response。学习web的第一步就是了解
HTML基础。因为所有的开发语言都是以HTML为基础的,如果你不了解基础,就会发现遇到问题无从下手。
如下,有一个 a.xxx 页面(注意:这里的xxx因为与语言无关,所以,他可以是a.asp,可以是a.aspx,也可以是a.jsp或者a.php等),其基础是
<form method="post" action="b.xxx" > <input type="text" name="txt" /> </form>
在上面代码里,你必须了解 form表单有2个极其重要的数学:method,采用什么提交方式:是get还是post, action:用来表示谁来接受这些参数。
里面name="txt"定义了控件的名字,这意味着,在后台可以通过 Request["txt"] 获取到这些参数。
有了这个基础,你会发现早期的 ASP.NET Web语法糖就很容易解决。下面的这段代码,已经简单到不能再简单的地方了:页面里放置了一个TextBox,点击button获取文本框的值。
<!DOCTYPE html> <script runat="server"> protected void Button1_Click(object sender, EventArgs e) { string content = txt.Text; } </script> <html> <head runat="server"> </head> <body> <form id="form1" runat="server" > <asp:TextBox runat="server" ID="txt"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /> </form> </body> </html>
但是,假如有一天,<asp:TextBox runat="server" ID="txt"></asp:TextBox>一下子变为 <input type="text" name="txt" />,相信很多初学者开始紧张了:没有了 runat="server",
我怎么获取用户的输入?
这个时候,就是考验基础的时刻到了,就像开头说的,“不管形势如何千万万化,但是万变不离其中”,不管ASP.NET你怎么封装,你最终都是Http的请求和相应,都要遵循HTML表单的原理。
因此,只要使用 string content= Request.Form["txt"]; 就可以轻而易举的获得用户的输入。
<!DOCTYPE html> <script runat="server"> protected void Button1_Click(object sender, EventArgs e) { string content= Request.Form["txt"]; } </script> <html> <head runat="server"> </head> <body> <form id="form1" runat="server" > <input type="text" name="txt" /> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /> </form> </body> </html>
面向对象编程和函数编程
面向对象编程,通常是面向过程的,而面向函数变成是面向函数的。例如,要求一个数组中最大的数,如果用 java开发是自己实现代码,然后在程序里调用。
public static int Max(int[]array) { int max=array[0]; for (int i=1;i<array.length;i++) { if(max<array[i]) { max=array[i]; } } return max; }
相反,函数编程通常直接调用函数,最直接的就是SQL:
select max(age) from table
在SQL里,直接调用 max() 函数即可,至于怎么实现,你不用关心。
Part2
.NET的扩展语法出现海量变化应该来自:模拟SQL和JavaScript,
.NET的利器:匿名函数和扩展方法(下述)
扩展方法允许对类进行自定义方法,而匿名函数最大的作用是完成了函数的闭包写法。
.NET 语法糖 Linq-----模拟SQL
.NET第一次产生大量语法糖的灵感应该来自于SQL,在数据库里,SQL在处理数据方面有着极简的的语法,例如获取年龄大于18岁并且小于25的人只要一句语法就够了
select * from table where age>18 and age<25
有鉴于SQL的简洁实用,.NET Linq应运而生。Linq中存在大量的扩展方法。在System.Linq命名空间中,存在两个使用极其广泛的类Enumerable和Queryable。他们都是返回的数据集。
下面代码是Linq一个简单的例子:
static void Main(string[] args) { List<Student> students = getInitStudents(); IEnumerable<Student> temp1 = students.Where(stu => stu.Age > 18 && stu.Age < 25); foreach (var t in temp1) { Console.WriteLine(t.Name + t.Age); } } public static List<Student> getInitStudents() { List<Student> stuList = new List<Student>(); stuList.Add(new Student { No = 1000, Name = "王欢", Sex = "女", Age = 20, Score = 50 }); stuList.Add(new Student { No = 1001, Name = "张燕", Sex = "女", Age = 21, Score = 89 }); stuList.Add(new Student { No = 1001, Name = "于强", Sex = "男", Age = 26, Score = 34 }); // 初始化数据 return stuList; } } class Student { public int No { get; set; } public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } public float Score { get; set; } } }
在代码里 IEnumerable<Student> temp1 = students.Where(stu => stu.Age > 18 && stu.Age < 25); 可以认为 .NET 通过扩展来模拟SQL语法。
如果仔细看Where语法源码,他的定义为
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
从函数签名可以看出:扩展方法Where从IEnumerable<TSource>类型的source中筛选出满足条件predicate的结果,返回值仍为IEnumerable<TSource>类型。
就像SQL语句一样,Linq可以选择你想要的单独的列,不是返回全部列。
var temp2 = stuList.Where(it => it.Age >= 20) .Select(x => new {name=x.Name,age=x.Age })
foreach (var t in temp2) { Console.WriteLine(t); }
.NET 语法糖----模仿Javascript的箭头函数
.NET语法越来越像Javascript,毕竟JS的强大大家有目共睹。js核心几个重点是:箭头函数,方法扩展,匿名方法。
在JS经典里,如果对每个元素求他的平方,需要写成:
// JS 代码 var data = [2, 4, 5, 6, 7]; data.forEach(function (item) { return item * item; } );
而使用箭头函数,可以写为
// JS 代码
data.forEach(x=>x*x);
看似一小步却是写法的一大步,因为他让程序可读性极大提高。在这方面.NET借鉴了JS的语法,在.NET里,参考上面的Linq,利用箭头函数,让C#的语法极其简化。
//C#代码
var temp2 = stuList.Where(it => it.Age >= 20) .Select(x => new {name=x.Name,age=x.Age }) .OrderBy(y=>y.name)
.NET 扩展方法应该也是借鉴JS的原型。如JS里数组没有求最大值的方法,但是通过原型很容易扩展
//给数组增加一个 Max函数
Array.prototype.Max = function () {
return Math.max.apply(null, this.map((seg) => {return +seg}))
}
var data = [2, 4, 5, 6, 7];
//现在任何一个数组都可以调用 Max方法
var result= data.Max();
在.NET里,扩展方法里,通过this实现,例如 WordCount(this String str) ,然后就可以把WordCount想 string的传统方法一样使用。
class Program { static void Main(string[] args) { string s = "Hello Extension Methods"; int i = s.WordCount(); } } public static class MyExtensions { public static int WordCount(this String str) { return str.Split(' ').Length; } }
以上介绍了.NET语言的趋势,因为只有了解了上面的语法,那么在你阅读.NET Framework源代码
https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,e73922753675387a 或者.NET CORE 源代码 https://github.com/dotnet/aspnetcore/blob/master/src/Http/Http/src/Builder/ApplicationBuilder.cs 更容易理解。