11.1.2LINQ语句

LINQ查询表达式以from子句开始,以select或者group子句结束。在这两个子句之间可以跟零个或者多个from、let、where、join或者orderby子句。

static void LINQQuery()
{
//Formula1.GetChampions()返回一个列表,quer变量只是一个赋值语句,只有使用了foreach才会执行查询
var query = from r in Formula1.GetChampions()
where r.Country == "Brazil"
orderby r.Wins descending
select r;
foreach (var r in query)
{
Console.WriteLine("{0:A}", r);
}
}

11.1.3扩展方法

如果有类的源码,继承就可以给对象添加方法。但如果没有源代码,则可以使用扩展方法,它允许改变一个类,但不需要该类的源代码。
扩展方法是静态方法,它是类的一部分,但实际上没有放在类的源代码中。假定PhoneCusStruct类需要一个Add()方法,但不能修改源代码,就可以创建一个静态类,把Add()方法添加为一个静态方法

public static class PhoneExtension
  {
    public static void Add(this PhoneCusStruct phoneCusStruct,string phone)
    {
    //
    }

注意扩展方法的第一个参数是要扩展的类型,它放在this关键字的后面。这告诉编译器,这个方法是PhoneCusStruct类型的一部分。在这个例子中,PhoneCusStruct是要扩展的类型。在扩展方法中,可以访问所扩展类型的所有公有方法和属性。
  调用:PhoneCusStruct p =new PhoneCusStruct();
      p.Add();//即使方法是静态方法,也需要使用实例方法的语法。
如果扩展方法与类中的某个方法同名,就不会调用扩展方法。类中已有的任何实例方法优先。

编译器会转换LINQ查询,以调用方法而不是LINQ查询。LINQ为IEnumerable<T>接口提供了各种扩展方法(扩展方法在上面介绍到),以便用户在实现了该接口的任意集合上使用LINQ查询。
定义LINQ扩展方法的一个类是System.Linq名称空间中的IEnumerable。只需要导入这个名称空间,就打开了这个类的扩展方法的作用域。下面是Where()扩展方法的实现代码:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,Func<TSource,bool> predicate)
{
foreach(TSource item in source)
{
if(predicate(item))
{
yield return item;
} }
}

  因为Where()作为一个泛型方法,所以它可以用于包含在集合中的任意类型。实现了IEnumerable<T>接口的任意集合都支持它。

相关链接

其因相关使用在应用环境中再学习!这里先做了解

12.动态语言扩展

12.1 DRL (System.Dynamic与System.Runtime.ComplierServices)

Dynamic Language Runtime动态语言允许添加动态语言,如Ruby和Python.

12.2 dynamic类型

dynamic的对象可以在运行期间改变其类型.其类型是有用的,但它是有代价的!

dynamic dyn;
dyn = ;
Console.WriteLine(dyn.GetType()); //输出System.int32
Console.WriteLine(dyn); //输出100 dyn = "This is a string";
Console.WriteLine(dyn.GetType()); //输出System.String
Console.WriteLine(dyn); //输出This is a string

12.3包含DLR ScriptRuntime

利用脚本完成工作,相关应用相对少,可请选读 因要了解python语言,暂时跳过

相关使用

13异步编程

13.1

1、Invoke() 调用时,Invoke会阻止当前主线程的运行,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念。
2、BeginInvoke() 调用时,当前线程会启用线程池中的某个线程来执行此方法,BeginInvoke不会阻止当前主线程的运行,而是等当前主线程做完事情之后再执行BeginInvoke中的代码内容,表现出“异步”的概念。

IAsyncResult rtn = 委托变量.BeginInvoke(……); // 启动异步调用
3、EndInvoke() ,在想获取 BeginInvoke() 执行完毕后的结果时,调用此方法来获取。

用于保存方法结果的变量=委托变量.EndInvoke(rtn); // 阻塞并等待异步调用结束

相关的说明   关于EndInvoke()的示例

13.3.1创建任务

static string Greeting(string name) //Greeting同步方法
{
Console.WriteLine("运行时访问的线程是:{0}与任务是:{1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId); Thread.Sleep();
return string.Format("Hello, {0}", name);
}
static Task<string> GreetingAsync(string name) //异步方法GreetingAsync返回的是Task<string>
{
return Task.Run<string>(()=>
{
return Greeting(name);
     Console.WriteLine("running greetingasync in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
});
}

13.3.2调用异步方法

private async static void CallerWithAsync()
{
Console.WriteLine((await GreetingAsync("Stephanie")); //async修饰符只能用于返回Task或Void的方法
}

13.3.3延续任务

ContinueWith方法定义了任务完成后就调用的代码(注:如任务清理工作可等)

private static void CallerWithContinuationTask()
{
Console.WriteLine("CallerWithContinuationTask线程为 {0} 任务 {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
var t1 = GreetingAsync("Stephanie");
t1.ContinueWith(t =>
{
string result = t.Result; // 访问任务返回的结果
Console.WriteLine(result);
Console.WriteLine("完成后的运行线程 {0} 任务 {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
});
} //输出为:
// CallerWithContinuationTask线程为 1 任务
// running greetingasync in thread 3 and task 1
// 运行时访问的线程是:3与任务是:1
// Hello, Stephanie
// 完成后的运行线程 4 任务 2

13.3.4同步上下文 相关链接 相关链接2

上下文简单理解为当时的环境即可,环境可以包括当时程序状态以及变量的状态,例如线程切换的时候在内核会发生上下文切换,这里的上下文就包括了当时寄存器的值,把寄存器的值都保存起来,等下次该线程又得到CPU时间的时候再恢复寄存器的值,这样线程才能正确的运行.

//如果不加上下文,那么就是以对象为线程锁定区域,如果加上下文,那么就是以逻辑上下文为锁定区域
[Synchronization(SynchronizationAttribute.REQUIRED, true)]
class synchronizationClass : ContextBoundObject
{
public void Start()
{
MessageBox.Show(Thread.CurrentThread.Name);
}
}

因为是使用SynchronizationAttribute来创建锁的,所以第一句[Synchronization(SynchronizationAttribute.REQUIRED, true)] 是必不可少的。

又因为是为ContextBoundObject对象创建锁,所以对象必须是ContextBoundObject,故必须继承ContextBoundObject。

两者缺一不可。测试:

synchronizationClass myclass = new synchronizationClass();
Thread thread = new Thread(new ThreadStart(myclass.Start));
thread.Name = "thread1";
Thread thread2 = new Thread(new ThreadStart(myclass.Start));
thread2.Name = "thread2";
thread.Start();
thread2.Start();

现象是thread1先弹框,点击确定后再弹thread2,原因就是整个对象都是一个锁,就是在thread1没处理完,thread2是无法进行操作的。
所以呢,上下文同步域会将整一个上下文全部锁定,就是说整个类都成为了一个锁,在线程1未走出该类,线程2就无法进入该类。
加入我把[Synchronization(SynchronizationAttribute.REQUIRED, true)]或者不继承ContextBoundObject发现此时的现象是thread1和thread2都会弹出框。
这就是锁与不锁的区别了。

13.3.5使用多个异步方法

1.按顺序调用异步方法 (按顺序使用await)

2.使用组合器

Task<string> t1 = GreetingAsync("Stephanie");await Task.WhenAll(t1, t2);//所有提供的任务都已完成时,才会返回Tack

Task.WhenAny()//在其中一个任何提供的任务已完成时,就会返回Tack

13.3.6 转换异步模式

转换为基于任务的异步模式  基于任务模式的异步的相关知识点

private static async void ConvertingAsyncPattern()
{
string r = await Task<string>.Factory.FromAsync<string>(BeginGreeting, EndGreeting, "Angela", null);//创建一个任务,它表示符合异步编程模型模式的成对的开始和结束方法。
Console.WriteLine(r);
}
/// <summary>
/// 从同步方法中借助委拖,创建一个异步方法
/// </summary>
private static Func<string, string> greetingInvoker = Greeting;
/// <summary>
/// 异步模式
/// </summary>
/// <param name="name">异步模式名</param>
/// <param name="callback">异步操作的状态</param>
/// <param name="state"></param>
/// <returns></returns>
static IAsyncResult BeginGreeting(string name, AsyncCallback callback, object state)
{
return greetingInvoker.BeginInvoke(name, callback, state);
} static string EndGreeting(IAsyncResult ar)
{
return greetingInvoker.EndInvoke(ar);
}

13.4.1异步方法的异常处理

static async Task ThrowAfter(int ms, string message)
{
await Task.Delay(ms);
throw new Exception(message);
}
private static async void HandleOneError()
{
try
{
await ThrowAfter(, "first");//如果不加入await的话 就无法捕捉异常!
}
catch (Exception ex)
{
Console.WriteLine("handled {0}", ex.Message);
}
}

13.4.2使用AggregateException信息

Task taskResult = null;
try
{
Task t1 = ThrowAfter(, "first");
Task t2 = ThrowAfter(, "second");
await (taskResult = Task.WhenAll(t1, t2));
}
catch (Exception ex)
{
// 第一个任务的异常信息,只显示在所有等待
Console.WriteLine("handled {0}", ex.Message);
foreach (var ex1 in taskResult.Exception.InnerExceptions)
{
Console.WriteLine("inner exception {0} from task {1}", ex1.Message, ex1.Source);
}
}

13.5取消

相关链接

private CancellationTokenSource cts = new CancellationTokenSource();
private void OnCancel(object sender, RoutedEventArgs e)
{
if (cts != null)
cts.Cancel();
}

13.5.2使用框架特性取消任务

private async void OnTaskBasedAsyncPattern(object sender,RoutedEventArgs e)
{
cts =new CancellationTokenSourcs();
try{
foreach(var req in GetSearchRequests())
var Client =new HttpClient();
var response = await Client.GetAsync(req.Url, cts.Token);//用以异步操作的 HTTP 完成选项和取消标记发送 GET 请求到指定的 URI。
string resp = await Response.Content.ReadAsStringAsync();
}
catch (OperationCanceledException ex)
{
MessageBox.Show(ex.Message);
}
}

13.5.3取消自定义任务

没测试!!跳过

private async void test()
{ await Task.Run(() =>
{
var images = req.Parse(resp);
foreach(var image in images)
{
cts.Token.ThrowIfCancellationRequested();
searchInfo.list.add(image);
}
}, cts.Token);
}

14内存管理与指针

int类型为为4个字节,即占用4个指针位. double占8个字节

14.2.值数据类型

参考C的示例
#include<stdio.h>
int *fun1(){ int a; return &a;}
int fun2(){ int b=; }
int main(){
int *p=fun1();
fun2();
printf("%d\n",*p);}

局部变量在函数调用完就会擦除(应该跟程序的联系),可是你使用局部变量时存放的是栈段,栈段的顺序是后进先出,而你刚好申请了相同大小的变量空间,系统直接就把那块空间又分配给你了,而里面的内容并没擦除。

14.2.3 垃圾回收

托管程序会自动更新地址,压缩堆形成一个连接的内存块

GC是一个垃圾回收机制 它主要是回收 托管对象 而不会回收 非托管对象 就像你使用某些非托管数据库链接对象的时候 就需要手动关闭 这些需要手动关闭的对象就是非托管对象 而这个就不是在GC管理范围之内
另外要说一下的是 GC这个东西很调皮 有时候GC的回收是没有固定时间的 随机的 所以 有时候我们需要手动关闭一些比较大的托管对象来提高性能

14.3 释放非托管的资源

14.3.2IDisposable接口

在C#中,推荐使用System.IDisposable接口替代折构函数

class ResouerceGobbler : IDisposable
{
public void Dispose()
{
}
}

ResouerceGobbler theInstance = new ResouerceGobbler(); //使用

//程序
theInstance.Dispose()  //释放

如果处理过程中出现异常,没有释放,所以应该使用

ResouerceGobbler theInstance = null;
try
{
theInstance = new ResouerceGobbler();
//程序
            }
finally
{
if (theInstance != null)
{
theInstance.Dispose();
}
}

以上代码有点混乱,所以有了下面的语法

using(  ResouerceGobbler theInstance = new ResouerceGobbler())
{
//程序
}

close()是调用dispose()的方法实现的

14.4用指针直接访问内存

使用指针的主要原因

1.向后兼容性

调用本地WindowsAPI函数,可以使用DllLmport声明,以避免使用指针

2.性能

一. 用unsafe 关键字编写不安全的代码

unasfe int GetSomeNumber(){} //表示这是一个不安全的方法! 也可以标记class或参数虚方法等,不能在局部变量本身标记为unsafe

如果要使用不安全变量,需要在不安全的方法中声明和使用它

VS可在项目属性窗口的Build选项中找到不安全代码的选项

二.指针的语法(命名时前面是小写p)

int* pWidth;    //*是在类型后面!!与变量无关 C++中是在变量上 如: int *pWidth ,要区分开

&表示取地址 int* pX =&x //表示pX指向x

3将指针强制转换为整数类型

int x=10; int* pX,pY; pX = &x; pY =pX; * pY =20;   uint y =(uint)pX; int* pD = (int*) Y;

4.指针类型之间的强制转换

double* pDouble = (double*) pByte//pByte指针转换为double指针,不会得到一个有意义的值. (合法的代码)

5.void指针

int* pointerToInt; void* pointerToVoid; pointerToVoid = (void*)pointerToInt;//很少用,主要用于调用需要void*参数API函数

6.指针算术的运算 +、-、+=、-=、++、--

int* pInt=&int变量; pInt += 1 //不允许对void指针运算,注意byte与char其总字节数不是4的倍数,不能使用P+X*(sizeof(T))算法

7sizeof运算符

int x =sizeof(double) //返double类型占用的字节数,注意不能用于计算类

8.结构指针:指针成员访问运算符

struct MyStruct
{public log X;
public float F;
}
MyStruct* pStruct; //定义一个指针
MyStruct Struct = new MyStruct(); //初始化
pStruct = &Struct; //通过指针访问结构成员
(*pStruct).X = ;
(*pStruct).Y =3.4f;

上述代码改写为

pStruct->X = ;
pStruct->Y = 3.4f;

类成员指针

对象存储在堆上,垃圾回收过程会变动,所以要使用fixed,语法如下

MyClass myObject =new MyClass();
Fixed (long* pX = &(myObject.X))
Fixed (float* pF = &(myObject.F))
{
//程序
}
//类型相同时可以放在一条fixed中 fixed(long* pX = &(myObject.X),pF = &(myObject.F))如果不同阶段固定指针,可以嵌套fixed块

14.4指针示例

使用{0:X}格式输出十六进制

15 反射

15.2.1编写自定义特性

下面为自定义元素时

[FieldNameAttribute("SocialSecurityNumber")]
public string SocialSecurityNumber
{
get{
//ect

1、AttributeUsage特性

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
//AllowMultiple = true 允许它多次应用到同一项上
 //Inherited = false如果该属性可以由派生类和重写成员继承,则为 true;否则为 false。 默认值为 true
public class LastModifiedAttribute : Attribute
{
public LastModifiedAttribute(string dateModified, string changes)
{
//程序
}
}
[LastModified("14 Feb 2010", "IEnumerable interface implemented So Vector can now be treated as a collection")]

15.3反射

15.3.1 System.type类

属性

Type intType=typeof(int); //Type的属性 name, fullname, Namepace命名空间, BaseType基类型 isClass是否为类

方法

Type intType = typeof(int);
MethodInfo[] methods = intType.GetMethods(); //取得该类型的法方
foreach (var test in methods)
{
Console.WriteLine(test);
}

15.3.3 Assembly类 System.Reflection

加载

Assembly theAssembly = Assembly.Load("VectorClass"); //查找程序集"VectorClass"
Assembly theAssembly = Assembly.LoadFrom(@"c:\12\Some"); //在c:\12\Some查找程序集"VectorClass"

1,获取程序集中定义的类型的详细信息

ype[] types = theAssembly.GetTypes();

2获取自定义特性的详细信息

Attribute supportsAttribute = Attribute.GetCustomAttribute(theAssembly, typeof (SupportsWhatsNewAttribute)); //获取程序集的特性

关于使用

Type T2 = typeof(TClass);
var Mets = T2.GetMembers();//获取所有公共成员(返回值是MemberInfo类型集合)
foreach (var m in Mets)
{
if (m.Name=="Equals")
{
Console.WriteLine("【" + m.MemberType.ToString() + "】:" + m.Name);
// m.MemberType 是成员类型 // m.DeclaringType;//获取申明该成员的类
// m.ReflectedType;//获取用于获取 MemberInfo 的此实例的类对象。 }
}

相关的附加链接

16 错误与异常

关于异常类的介绍

try
{
throw new Exception("ft");
}
catch (OverflowException ex)
{ }
catch (Exception ex)
{ }
finally
{
//程序完成后一定会执行的操作
}

C#高级编程笔记(11至16章)异步/托管/反射/异常的更多相关文章

  1. C#高级编程笔记之第三章:对象和类型

    类和结构的区别 类成员 匿名类型 结构 弱引用 部分类 Object类,其他类都从该类派生而来 扩展方法 3.2 类和结构 类与结构的区别是它们在内存中的存储方式.访问方式(类似存储在堆上的引用类型, ...

  2. C#高级编程第11版 - 第九章 索引

    [1]9.1 System.String 类 String类中关键的方法.如替换,比较等. [2]9.1.1 构建字符串 1.String类依然有一个缺点:因为它是不可变的数据类型,这意味当你初始化一 ...

  3. C#高级编程第11版 - 第二章 索引

    [1]2.1.1 Hello,World! 1. using static System.Console; // ... WriteLine("Hello World!"); 提前 ...

  4. Android高级编程笔记(四)深入探讨Activity(转)

    在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一 ...

  5. 《深入Java虚拟机学习笔记》- 第16章 控制流

    <深入Java虚拟机学习笔记>- 第16章 控制流

  6. C#高级编程笔记之第二章:核心C#

    变量的初始化和作用域 C#的预定义数据类型 流控制 枚举 名称空间 预处理命令 C#编程的推荐规则和约定 变量的初始化和作用域 初始化 C#有两个方法可以一确保变量在使用前进行了初始化: 变量是字段, ...

  7. 《Node.js 高级编程》简介与第二章笔记

    <Node.js 高级编程> 作者简介 Pedro Teixerra 高产,开源项目程序员 Node 社区活跃成员,Node公司的创始人之一. 10岁开始编程,Visual Basic.C ...

  8. C#高级编程笔记 (6至10章节)运算符/委托/字符/正则/集合

    数学的复习,4^-2即是1/4/4的意思, 4^2是1*2*2的意思,而10^-2为0.01! 7.2运算符 符号 说明 例   ++ 操作数加1 int i=3; j=i++; 运算后i的值为4,j ...

  9. UNIX环境高级编程笔记之文件I/O

    一.总结 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情.其实大概三年前,那会大三,我就买了这本书 ...

随机推荐

  1. sscanf sscanf_s使用

    #include<stdio.h> 定义函数 int sscanf (const char *str,const char * format,........); 函数说明  sscanf ...

  2. 关于C(n,m) 的奇偶 ,与C(n,0),C(n,1),C(n,2)…C(n,n).当中有多少个奇数

    (n & m) == m  为奇数 C(n,0),C(n,1),C(n,2)…C(n,n).当中有多少个奇数 第一种想法是Lucas定理推导,我们分析一下 C(n,m)%2,那么由lucas定 ...

  3. VS code 同步设置与插件

    准备工作:拥有一个github账户,电脑上需安装VSCode.实现同步的功能主要依赖于VSCode插件 "Settings Sync"第一步:安装同步插件Settings Sync ...

  4. STM32 在串口通信时运用MODBUS协议

    最近一个项目用到了MODBUS协议,就学习了一下,这里做一下记录以免后续忘记. 要用到MODBUS肯定要先知道是MOBUS协议,这里呢我们就又要先理解协议的含义了. 所谓的协议是什么?就是互相之间的约 ...

  5. Vagrant 手册之 Vagrantfile - 概述

    原文地址 Vagrantfile 的主要用途是描述用于项目的机器类型,以及如何配置和提供这些机器. Vagrant 的每个项目运行一个 Vagrantfile,并且 Vagrantfile 应该被提交 ...

  6. libOpenThreads库链接冲突错误

    最近在linux 上安装了3.7.0版本的OpenSceneGraph,而在安装之前没有完全卸载之前安装的3.6.3版本,导致在编译程序链接时出现库引用冲突,在便以后出现以下警告信息: /usr/bi ...

  7. 使用bootstrap制作网站导航

    除了制作选项卡和下拉菜单,bootstrap还能编写出美观的网站导航栏 一.仿知乎导航栏 <body> <nav class="navbar navbar-default ...

  8. java_第一年_JavaWeb(9)

    JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ...

  9. Codeforces 1156E Special Segments of Permutation(单调栈)

    可以用单调栈直接维护出ai所能覆盖到的最大的左右范围是什么,然后我们可以用这个范围暴力的去查询这个区间的是否有满足的点对,一个小坑点,要对左右区间的大小进行判断,只需要去枚举距离i最近的一段区间去枚举 ...

  10. python学习第二十二天文件byte类型

    所有的文件在计算机里面存储为二进制形式,但是我们有时候有需要将二进制转换为gbk或者utf-8形式,编码的时候encode 解码的时候decode ,下面简单阐述python二进制在文件传输过程的作用 ...