您的位置:首页 > 编程语言 > C#

C#使用Tips(部分)

2015-12-15 18:58 471 查看

语法要点

一些基本的编程范式

类名尽量有具体的实际意义

类名每个单词首字母大写

类中成员变量首字母小写,之后的单词的首字母大写,如
alarmClock


类中方法变量每个单词首字母大写,如
GetPulse()


结构体定义之前加上S,接口定义之前加上I

使用
/     /
注释,不使用
/*    */
注释

全局变量定义之前加上g

关于类的权限问题的说明

一般情况下,优先使用protected、其次使用private,最后使用public

当类可能需要被继承时,优先考虑protected;当类不太有可能需要被继承时,优先考虑private

定义类的名称时,一定要先考虑好它的作用以及相应的方法

泛型编程

引入背景

为了说明方法所有可能的数据类型而需要覆写某种方法或者某种方法集合的时候,会发生代码膨胀

为解决这个问题,引入泛型编程的概念

代码如下

函数定义如下

static void SwapTwoNum<T>(ref T val1, ref T val2)
{
T swap;
swap = val1;
val1 = val2;
val2 = swap;
}


在在函数中调用如下

int a = 1, b = 2;
double c = 1.0, d = 2.0;
SwapTwoNum<int>(ref a,ref b);
SwapTwoNum<double>(ref c, ref d);


可以实现对a,b和c,d的值的交换(此处使用引用类型直接改变变量的值)不用对函数进行覆写,直接改变函数后T的类型即可

注:泛型不能对2个不同的数据类型进行操作,比如若要定义
Swap<T1,T2>(ref T1 val1 , ref T2 val2)
则在运行时会出错。

Static的说明:

函数中的static表示该变量只在第一次进入该函数时会赋给一个初值,以后进入时直接调用上次的值

类中静态成员表示不需要实例化就可以直接查看该成员信息,调用方法是:”类名.成员名”。如果不加static关键字,则需要在实例化类之后,再在具体的类之后调用该成员信息

继承:

子类可以继承基类的除私有以外的所有成员和方法,想重写基类的方法时,需要首先在基类中用virtual声明方法,再在子类中用override(覆盖)关键字声明该方法

接口(Interface)

注意的问题

接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员。

接口成员是自动公开的,且不能包含任何访问修饰符。

接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。

包括显式接口和隐式接口

隐式接口

如下例,
void ImplicitBark();
是隐式接口,类继承该接口时,需要重新定义该接口
public void ImplicitBark()


关于调用隐式接口的方法

way 1

IBark ie = new InterfaceExample();
ie.ImplicitBark();


way 2

InterfaceExample ie = new InterfaceExample();
ie.ImplicitBark();


显式接口

需要通过
void IBark.ExplicitBark()
来定义该方法,而且不能用public、protected、private等定义

显示接口的定义方法

way 1

IBark ie = new InterfaceExample();
ie.ExplicitBark();


注:隐式接口的第二种方法在此处不适用,否则会报错。若是想用,需要进行强制类型转换

InterfaceExample ie = new InterfaceExample();
((IBark)ie).ExplicitBark();


代码

类和接口定义

public interface IBark
{
void ImplicitBark();
void ExplicitBark();
}
public class InterfaceExample : IBark
{
public InterfaceExample()
{
}

public void ImplicitBark()
{
Console.WriteLine(" this is ImplicitBark ");
}

void IBark.ExplicitBark()
{
Console.WriteLine(" this is ExplicitBark ");
}
}


main.c

IBark ie = new InterfaceExample();
ie.ImplicitBark();ie.ExplicitBark();


隐式接口存在的意义

一般情况,当类或者结构要实现的是单个接口,可以使用隐式实现。

如果类或者结构继承了多个接口且接口中具有相同名称成员时,就要用到显式实现,当显式实现方式存在时,隐式实现方式就失效了。

系统中常用的静态类

Math

DateTime

Random

字符串相关说明

StringBuilder比String操作要快得多

可以通过格式化控制符进行输出,比如说工资、时间等变量,可以输出为固定的格式,用法为String.Format….

数组

一维数组

定义

数据类型[ ] 数组名

int[] a;


初始化

静态初始化

将所有的元素初始值列举出来

string[] b ={ "篮球", "足球", "排球", "网球", "羽毛球", "乒乓球" };


动态初始化

先固定数组大小,没有赋初始值

int[] a = new int[10];


遍历访问数组

foreach

foreach(类型 标识符 in array)

foreach(int i in ArrayA)


二维数组

定义

int[ , ] a;


初始化

静态

int[ , ] a ={ { 3, 5, 7 }, { 2, 4, 6 }, { 9, 5, 1 } };


动态

float[ , ] score = new float[7,5];


锯齿状数组

int [][] a = new int[12][];
,该二维数组的每一行的元素个数都可以不相同

创建数组的静态方法

Array arr = Array.CreateInstance(Type type, int[]length, int[]lowbound);


只能用SetValue和GetValue获取或者对数组进行赋值

数组的基本属性

Length:长度

Rank:维度

Clone:复制

b = (int[])a.Clone();
:将a复制到b中

复制之后b的长度被改变,创建一个关于a的浅表副本

改变b的值,不改变a的值,即目标数组和源数组是独立的

CopyTo:复制

a.CopyTo(b,2);
:将a复制到b中,b从b[2]开始改变

注意要使数组下标符合要求

这样赋值之后改变b,不会对a造成影响,即a和b是独立的

关于复制还有一种方法

代码

int[] a = { 1, 2, 3, 4, 5, 6, 7 };
int[] b = a;


相当于创建一个关于a的引用,之后改变b中元素的值,a中元素的值也会跟着改变

利用程序运行时间间接测量算法复杂度

用DateTime类相减是不准的,因为.NET中还有线程处理以及无用单元收集等其他事情需要处理,测得的时间会和算法复杂度运行时间相差很多

常用以下方法测量算法运行时间(不考虑编译器处理其他事情消耗的时间)

TimeSpan duration;
/*algorithm you want to check should be placed here*/
//...
/*end of you algorithm*/
duration = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine(duration.TotalSeconds);


数据结构

基础的排序算法

冒泡排序

选择排序

插入排序

基础的查找算法

顺序查找

二叉查找

递归的二叉查找算法

栈(Stack)

采用LIFO(先入后出)的结构,主要应用如下

算术运算

进制转换

进制转换函数

//将10进制的数num转化为b进制的数,将转化后的数以栈的形式返回
//栈的顶部是最高位,底部是最低位
static Stack HexConversion(int num, int b)
{
Stack digits = new Stack();
do
{
digits.Push(num % b);
num /= b;
}while( num != 0 );
return digits;
}


观察结果的代码如下

Stack stack4Three = new Stack();
stack4Three = HexConversion(100,8); //将100的10进制转化为8进制
while (stack4Three.Count > 0)
{
Console.Write(stack4Three.Pop());
}
Console.WriteLine();


队列(Queue)

常用组件

ImageList

可以将一组图片加入到该集合中,之后可以通过下标去访问该图片集合

可以用来显示动画(先将一组图片放在集合中,再循环显示即可)

Timer

可以实现固定的时间间隔执行某段程序,相当于定时中断

常用于定时刷新界面等,如果时间显示

菜单

MenuStrip

ToolStrip

对话框

文件选择对话框

文件操作

文件

这里主要是对文件进行复制、删除、移动、新建等操作

File

静态类,不需要实例化

FileInfo

必须被实例化才能使用

文件夹

Directory

静态类,不需要实例化

DirectoryInfo

必须被实例化才能使用

文件读写

引入流的概念,对文件读或写

字节序列化的抽象概念,串行化设备的抽象表示

留得基本操作

Read

Write

Seek:查找(网络流一般不支持查找)

创建文件流的方法

FileStream类

写入文件时,需要将字符串转换为字节数组,实现方法如下

string a = "123";
ASCIIEncoding b = new ASCIIEncoding();
byte[] c = b.GetBytes(a); //


之后就可以将字节数组c写入文件中,如果此时a字符串是中文字符,则转换的过程中会出现信息丢失的现象(只保留低8位)

GDI图形图像处理相关

坐标系的概念

GDI有3种坐标系

世界坐标系

设备坐标系

页面坐标系

图形绘制相关技巧

错误的尝试

在窗口中绘制好图像后,改变窗口大小或者最小化、最大化等操作时,绘制的图像会“消失”,要想使图像信息不丢失,需要在窗口中添加Paint事件,每次绘制时,需要重新绘制该图像

private void CClockExercise_Paint(object sender, PaintEventArgs e)
{
Graphics Pic = CPbDispGraph.CreateGraphics();
Pen MyPen = new Pen(Color.Red);
Pic.DrawEllipse(MyPen
, 0, 0
, CPbDispGraph.Width - 1, CPbDispGraph.Height - 1);
Pic.DrawLine(MyPen
, new Point(0, 0)
, new Point(CPbDispGraph.Width - 1, CPbDispGraph.Height - 1));
Pic.Dispose();
}


注:这种方法实现重绘时,速度比较慢,有时改变控件大小后,需要较长时间才能看到改变后的效果。

慢的原因

在Form的重绘函数中想要重绘PictureBox的窗口,速度就慢下来了,要想加快速度,需要直接在需要重绘的窗口中调用该窗口的重绘函数

改进后的代码如下:

private void CPbDispGraph_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
PointF[] pt = new PointF[360]; //定义点数组
using (Pen pen = new Pen(Color.Black)) //定义画笔
{
for (int i = 0; i < 720; i += 2) //计算获得曲线上每个点的坐标
{
pt[i / 2].X = i / 2;
pt[i / 2].Y = (float)(60 - 50 * Math.Sin(Math.PI / 180 * i));
}
g.DrawLine(pen, 0, 60, 400, 60); //绘制一条表示数轴的直线
g.DrawCurve(pen, pt); //绘制基数样条构成的正弦曲线
}
}


这段代码是PictureBox的重绘函数

描述坐标系的基本结构

Point和PointF

Size和SizeF

Rectangle和RectangleF

基本的GDI对象

画笔(Pen)

笔刷(Brush)

关于图像双缓冲的说明

图像显示时,会涉及到刷新的问题,窗口上控件太多或者刷新速度太快时,往往会出现图像闪烁的问题,因为程序一直在刷新;而如果等用户画完之后再输出就不会出现这种情况。

solution:新建一个Bitmap的画布,将所有的东西先画到画布上,再将画布一次性加载到窗口中,可以避免屏幕闪烁的情况

代码

Bitmap bmpBuffer = new Bitmap(CPbRealTimePlot.Width , CPbRealTimePlot.Height);
Graphics g = Graphics.FromImage(bmpBuffer);
//以下的Using表明pen的作用域,当这段代码执行结束之后,会释放pen资源
using (Pen pen = new Pen(Color.Blue)) //定义画笔
{
//数据平移与计算
for (int i = 0; i < NUM_TO_DISP-1; i++)
{
ptForRealTimeDisp[i].Y = ptForRealTimeDisp[i + 1].Y;
}
ptForRealTimeDisp[NUM_TO_DISP-1].Y = 50 + 50 * (float)Math.Sin(2*Math.PI* numForSinPlot/NUM_TO_DISP);
numForSinPlot++;
if (numForSinPlot == NUM_TO_DISP)
numForSinPlot = 0;
//绘图
g.Clear(Color.White); // 首先清除图像,再进行绘制
g.DrawLine(pen, 0, 50, 400, 50); //绘制一条表示数轴的直线
g.DrawCurve(pen, ptForRealTimeDisp); //绘制基数样条构成的正弦曲线
}
//下面这段代码将Bitmap资源释放到窗口中并显示
using (Graphics tg = CPbRealTimePlot.CreateGraphics())
{
tg.DrawImage(bmpBuffer, 0, 0);
}


函数或者方法数据传递的区别

链接网址

值传递

在通过值传递作为方法参数的变量时,传递给方法的是数据副本。在方法中对该数据的任何修改都不会对初始值有任何影响。

static void DoSomething(int parameter)


引用传递

如果传递引用的话,那么无论在程序的什么地方作改变的话(可能是在另一个方法、属性中,甚至是另一个对象中),都会改变使用改引用的值。对方法中任何参数的改变都将影响方法的返回值。

static void DoSomething(ref int parameter)


值传递引用类型

传递的是对象的引用

static void DoSomething(Person somePerson)


如果按照如下方法,则不会修改主程序中somePerson的一些属性

static void DoSomething(Person somePerson){
somePeron=new Person(100); //创建一个新对象,赋值会不起作用
}


如果按照以下方法,则会修改主程序中somePerson的一些属性

static void DoSomething(Person somePerson){
somePerson.Age=100; //这个对象相当于一个引用,直接改变其属性即可
}


some other tips

获得服务器的运行时间

Environment.TickCount
:以毫秒为单位 ,一般对应开机时间

窗口大小改变时,窗口内控件大小也相应发生改变

为窗口添加ResizeBegin事件

private void CClockExercise_ResizeBegin(object sender, EventArgs e)
{
BeforeSize = this.Size;//获取之前的窗口大小
}


为窗口添加ResizeEnd事件

private void CClockExercise_ResizeEnd(object sender, EventArgs e)
{
Size EndSize = this.Size;
float percentWidth;
float percentHeight;
//获得变化比例
percentWidth = (float)EndSize.Width / BeforeSize.Width;
percentHeight = (float)EndSize.Height / BeforeSize.Height;

ChangeAllSzie(this,percentWidth,percentHeight);//调用递归函数,改变控件的大小
}


其中,上面的ChangeAllSzie函数是递归的,描述如下

private void ChangeAllSzie(Control control , float percentWidth , float percentHeight)
{
foreach (Control ctrl in control.Controls)
{
//按比例改变控件大小
ctrl.Width = (int)(ctrl.Width * percentWidth);
ctrl.Height = (int)(ctrl.Height * percentHeight);
//为了不使控件之间覆盖 位置也要按比例变化
ctrl.Left = (int)(ctrl.Left * percentWidth);
ctrl.Top = (int)(ctrl.Top * percentHeight);
if (ctrl.HasChildren)//如果容器中还有子容器,则进行递归
{
ChangeAllSzie(ctrl, percentWidth, percentHeight);
}
}
}


注意

此时,窗口的FormBorderStyle属性一定要设置为Sizable

当最大化或者最小化窗口时,控件大小不发生改变,只有拖动窗口改变其大小时,控件大小才相应随之改变

关于添加事件后,删除事件对应代码,程序运行出错的说明

在双击添加事件后,VS做了

添加事件响应代码

在”窗口名.Designer.cs”中添加了
this.button1.Click += new System.EventHandler(this.button1_Click);
,这通常在
#region Windows 窗体设计器生成的代码
中隐藏,需要将其展开

如果需要删除对应的事件响应,需要同时删除以上2处才可以

执行CMD命令

包含命名空间

using System.Diagnostics;


调用
Process.Start("CMD.Exe");
,或者其他命令也可以

CLR(Common Language Runtime)

定义:公用语言运行时

相当于一个运行环境,C#先编译成中间语言,再在CLR上面执行

Dispose资源释放相关

资源

在CLR出来之后,Windows系统资源开始分为“非托管资源”和“托管资源”。

非托管资源是

所有的Window内核对象(句柄)都是非托管资源,如对于Stream,数据库连接,GDI+的相关对象,还有Com对象等等,这些资源并不是受到CLR管理;

需要显式释放的,也即需要你写代码释放

托管资源是

由CLR管理分配和释放的资源,即由CLR里new出来的对象。

并不需要显式释放,但是如果引用类型本身含有非托管资源,则需要进行现实释放

释放规则

新建窗口等资源时,因为受系统管制,资源回收速度较快,因此不需要Dispose回收

GDI绘图中,如果新建画笔、笔刷、图像等对象时,因为比较占用系统资源,因此在函数执行结束,即绘图完成时,需要将其释放,用pen.Dispose()即可。或者采用以下方法:

using (Pen pen = new Pen(Color.Black)) //定义画笔
{
for (int i = 0; i < 720; i += 2) //计算获得曲线上每个点的坐标
{
pt[i / 2].X = i / 2;
pt[i / 2].Y = (float)(60 - 50 * Math.Sin(Math.PI / 180 * i));
}
g.DrawLine(pen, 0, 60, 400, 60); //绘制一条表示数轴的直线
g.DrawCurve(pen, pt); //绘制基数样条构成的正弦曲线
}


这是确定了Pen的生命周期,即这段代码执行完之后,Pen资源就会被系统释放。

因为重绘图像时,图像是作为参数传进来的,在结束时,不需要Dispose图像,直接由系统控制其生命周期就行。

关于TextBox限制数字输入的问题

为TextBox添加KeyPress的事件,代码如下

private void CTbSecondSet_KeyPress(object sender, KeyPressEventArgs e)
{
if ((!Char.IsNumber(e.KeyChar))
&& (e.KeyChar != (char)8)) //判断按下的字符是数字或者退格,若都不是,则提示用户输入数字
{
e.Handled = true;
MessageBox.Show("请输入数字");
}
else
{
e.Handled = false;
}
}


如需要对数字判断大小,看是否在合理范围内,则需要通过给TextBox添加Leave事件,代码如下

private void CTbHourSet_Leave(object sender, EventArgs e)
{
if (CTbHourSet.Text.Equals(""))
CTbHourSet.Text = "0";
if (Convert.ToInt32(CTbHourSet.Text) < 0
|| Convert.ToInt32(CTbHourSet.Text) >= 24)
{
CTbHourSet.Clear();
MessageBox.Show("请输入有效的时间范围");
}
}


获取鼠标在屏幕上的位置

电脑屏幕

Point pt = MousePosition;
,得到鼠标的值,可以通过
pt.X
pt.Y
得到其X、Y的坐标值,原点是电脑屏幕左上角

Point pt2= this.PointToClient(pt);
,获得鼠标在窗体上的坐标值,即以窗体的原点为屏幕原点,对pt进行整体平移

关于在工程中考虑问题的一些方法

原谅我还没想好标题

对于比较的问题,比如说闹钟到达时间就触发某一事件,则触发条件需要设置得尽量严苛。不能是简单地对时间进行比较就结束,而是应该记录上次的时间,当当前时间大于等于闹钟时间且上次时间小于闹钟时间时,触发闹钟响应事件。即用线与点进行比较。这是因为windows的系统时间为了和网络时间进行校准,有时会发生跳变,有可能恰好跳过闹钟时间,此时就需要采用该种方法对闹钟时间进行判断。

在实时数据采集处理过程中,这种“点对线”的思想十分常用,因为离散控制系统中,数据很容易发生跳变,涉及比较时,采用这种思想可靠性会更高。

代码异常处理

在写代码时,一定要考虑到各种可能出现的条件,尽可能分情况讨论并给用户提示以便于解决问题,尽可能不用
try...catch...
抛出异常。

指标的关系

每个设计任务的指标都是有其一定的背景的,不要认为指标看起来没有什么用就不去管它,否则可能会丢掉很多细节

WPF操作相关

使用dll或者外部库

在“解决方案”里右击“引用”,添加dll的引用;

在toolbox里右击,单击“选择项”,在wpf组件中选择“浏览”,选中加载的dll,即可在“所有WPF组件”中找到新加的控件了

Silverlight使用相关

安装

尼玛,这个花了我2天!!!

安装需要版相同的tools和SDK,我当时就是安装了不同版本的,所以程序可以运行但是设计器中观察不了,安装tools时,其实就将runtime也安装了(包含在里面)

VS2010来说,最好使用3.0或者4.0版本的Siverlight,因为如果要用5.0版本的,需要安装VS补丁包,比较麻烦。

先安装SDK,再安装tools

sharepoint相关

在sharepoint中插入webpart部件

有以下几种方法

* 直接新建webpart然后插入xap文件an,不过对于xap的url地址,我不是特别清楚,也没有尝试成功

* 先将silverlight产生的xap文件保存在sharepoint的文档库中,此时xap文件的url地址更加方便一点,找到那个文档,右击复制链接即可

关于实习的过程中silverlight、WPF、WCF通讯相关的问题

通讯简介

实习的工程项目是BS架构,通讯采用的是客户端对象模型,因此需要在本地实时地获取sharepoint数据,通过VS导入sharepoint数据。

关于通讯,WPF和sharepoint通讯是利用的同步通讯,即而silverlight作为webpart,在网页中进行相关操作时利用的异步通讯,因此在此过程中需要利用异步编程方法。

关于webpart的引入文件,即xap文件的放置问题,如果放在本地(服务器需要能够与访问到本地路径才可),网页相关的缓存可能会使刚刚在文件目录里更新的文件得不到及时的引用,即浏览器直接引用浏览器之前的缓存了;因此,选择xap文件放在sharepoint的文档库中,这样因为sharepoint的安全保护问题,会使浏览器对该网页的缓存无效,即每次引入时都是最新的文档,可以保证网页的实时刷新

WPF操作过程中的数据的增删改查相关问题

准备工作

在数据源中添加sharepoint数据,需要填写添加网页的网址,VS会自动生成基于sharepoint的引用以及相关的命名空间等。

相关代码

初始化

private CStopCondition stopCondition = new CStopCondition();
private ProTest.温升实验DataContext dc = null; //重点!之后都是对这个对象进行操作


数据连接服务

private bool IsConnect( )
{
try
{
dc = new ProTest.温升实验DataContext(
new Uri("http://win-ubfvccleemg/sites/ProTest/_vti_bin/ListData.svc/"));//存储数据的网址
//dc.Credentials = CredentialCache.DefaultCredentials;
NetworkCredential nc = new NetworkCredential("jiang", "qwer1234-");//帐号和密码
dc.Credentials = nc;
return true;
}
catch
{
return false;
}
}


增加数据项

private bool AddData(CStopCondition cSc)
{
if (dc.停止条件列表.Where(c => c.名字 == cSc.name).FirstOrDefault() == null)
{
ProTest.停止条件列表Item pt = new ProTest.停止条件列表Item();
pt.名字 = cSc.name;
pt.数据 = cSc.Serialize();
pt.标准 = cSc.referCriterion;
pt.描述 = cSc.description;
pt.参数 = cSc.parameters;
pt.种类 = cSc.kind.ToString();
dc.AddTo停止条件列表(pt);
dc.SaveChanges();
return true;
}
else
{
return false;
}
}


修改数据项

private bool ChangeData()
{
int num = dc.停止条件列表.Where(c => c.名字 == stopCondition.name).Count();
if (num >= 1 && (nameOld != stopCondition.name))
{
return false;
}
else
{
var item = dc.停止条件列表.Where(c => c.名字 == nameOld).FirstOrDefault();
item.名字 = stopCondition.name;
item.数据 = stopCondition.Serialize();
item.标准 = stopCondition.referCriterion;
item.描述 = stopCondition.description;
item.参数 = stopCondition.parameters;
item.种类 = stopCondition.kind.ToString();
dc.UpdateObject(item);
dc.SaveChanges();
return true;
}
}


查询数据项

private bool QueryData(string name)
{
if (dc.停止条件列表.Where(c => c.名字 == name).FirstOrDefault() != null)
{
var results = (from item in dc.停止条件列表
where item.名字 == name
select new
{
data = item.数据
});
string str = "";
foreach (var res in results)
{
str += res.data;
}
MessageBox.Show(str);
return true;
}
else
{
return false;
}
}


删除数据项

private bool DeleteData(string name)
{
if (dc.停止条件列表.Where(c => c.名字 == name).FirstOrDefault() != null)
{
dc.DeleteObject(dc.停止条件列表.Where(c => c.名字 == name).FirstOrDefault());
dc.SaveChanges();
return true;
}
else
{
return false;
}
}


silverlight操作sharepoint数据以及将xap部署到sharepoint的webpart中去的问题

网页部署相关问题

silverlight工程生成解决方案后会在
SilverlightApplication1\SilverlightApplication1.Web\ClientBin
的文件夹中生成xap文件,将此文件放入sharepoint的文档库中,然后在网页中插入webpart,其指定的路径即xap存储对应的路径。也可以放在服务器可以访问到的路径,但此时网页缓存的问题难以解决

相关操作

说明:因为silverlight和sharepoint关联时,是进行异步通信的,对数据的增上改查等操作都需要异步通信编程

* 初始化

private Condition stopCondition = new Condition();
private PageProperty pagePro = PageProperty.IsAdd;//存储网页是新建还是编辑
private ProTest.温升实验DataContext dc = null;
//进入该网页时,会有相关信息,
//包括操作的数据项(如果有的话),以及跳转的原网页等信息,将其存储在字典里
private IDictionary<string, string> webInfo = HtmlPage.Document.QueryString;


* 增加数据

private void AddData(Condition cSc)
{
bool addFail = false;

//异步
try
{
dc.StopCondition02.BeginExecute((result) =>
{//lamda表达式
try
{
var items = dc.StopCondition02.EndExecute(result);
//下面这句话需要尝试一下,因为之前这个查询的任务不能运行
//if (items.Where(c => c.名字 == stopCondition.name) != null)
foreach (var item in items)
{
if (item.名字 == stopCondition.name)
{
addFail = true;
break;
}
}
if(addFail)
{
CTbForDebug.Text += "新建页中已有该名称,无法添加停止条件\n";
}
else
{
ProTest.StopCondition02Item pt = new ProTest.StopCondition02Item();
pt.名字 = cSc.name;
pt.数据 = cSc.Serialize();
pt.标准 = cSc.referCriterion;
pt.描述 = cSc.description;
pt.参数 = cSc.parameters;
pt.种类 = cSc.kind.ToString();
dc.AddToStopCondition02(pt);
dc.BeginSaveChanges((ar) =>
{
if (ar.IsCompleted)
{
CTbForDebug.Text += "添加成功\n";
CloseThisPage();
}
else
{
CTbForDebug.Text += "添加失败\n";
}
}, null);
}
}
catch (Exception ex)
{
CTbForDebug.Text += ex.Message;
}
}, null);
}
catch(Exception ee)
{
MessageBox.Show(ee.ToString());
}
}


* 编辑数据

编辑数据的语句和添加数据类似,只是有以下几个地方需要注意:

* 需要新建一个数据项的对象,当var对象找到时(数据库中对应的数据项),将var类型隐式转换为数据项对象,之后直接修改这个数据项的对象即可

* 修改结束后,需要利用以下方式进行更新

//dc.AttachTo("StopCondition02", (ProTest.StopCondition02Item)forChg);//这句话不加竟然也可以运行成功。。
dc.UpdateObject(forChg);
第一句是将数据和数据项进行关联,然而自己操作的时候发现根本不需要这一句。。boss之前测试说需要,我就先在这里注释掉,不行再加上。。
* 保存数据库


* 保存数据

dc.BeginSaveChanges((ar) =>
{
if (ar.IsCompleted)
{
CTbForDebug.Text += "修改成功\n";
CloseThisPage();
}
else
{
CTbForDebug.Text += "修改失败\n";
}
}, null);


* 注:关于lamda表达式的使用问题

* 当初它的引入是为了方便编程,即省略某些函数的作用

* 现在发现,siverlight操作sharepoint的数据时,我因为不熟,不敢随意改,导致现在的函数都是有多层嵌套的问题,显得特变乱。

* 当嵌套层次比较多时,不建议用lamda表达式,直接用普通的异步编程即可。。然而我并没有学过。。

C#生成二维码

dll文件

ThoughtWorks.QRCode.dll

添加引用之后,需要在程序开始处添加
using ThoughtWorks.QRCode.Codec;


生成二维码函数

代码如下

private void GenerateQR()
{
//Image image;
//image = qrCodeEncoder.Encode(data, Encoding.UTF8);
//MemoryStream ms = new MemoryStream();
//image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
//byte[] bt = ms.ToArray();
}

/// 生成二维码
/// </summary>
/// <param name="strData">要生成的文字或者数字,支持中文。如: "4408810820 深圳-广州" 或者:4444444444</param>
/// <param name="qrEncoding">三种尺寸:BYTE ,ALPHA_NUMERIC,NUMERIC</param>
/// <param name="level">大小:L M Q H</param>
/// <param name="version">版本:如 8</param>
/// <param name="scale">比例:如 4</param>
/// <returns></returns>
public void CreateCode_Choose(string strData, string qrEncoding, string level, int version, int scale)
{
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
string encoding = qrEncoding;
switch (encoding)
{
case "Byte":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
break;
case "AlphaNumeric":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
break;
case "Numeric":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.NUMERIC;
break;
default:
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
break;
}
qrCodeEncoder.QRCodeScale = scale;
qrCodeEncoder.QRCodeVersion = version;
switch (level)
{
case "L":
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
break;
case "M":
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
break;
case "Q":
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
break;
default:
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
break;
}
//文字生成图片
Image image = qrCodeEncoder.Encode(strData);
string filename = DateTime.Now.ToString("yyyymmddhhmmssfff").ToString() + ".jpg";
string filepath = @"./jpg/";
//如果文件夹不存在,则创建
if (!Directory.Exists(filepath))
Directory.CreateDirectory(filepath);
FileStream fs = new FileStream(filepath+filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);
fs.Close();
image.Dispose();
}


说明

使用如下代码即可生成二维码

代码

private string data = "233333";
CreateCode_Choose(data , "BYTE" , "L" , 8 , 4 );//这里的参数均是比较常用的参数


注:这种方法适合生成数字或者中英文字符的文本

将图片插入二维码中

代码

public Image GCode(String data)
{
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
qrCodeEncoder.QRCodeScale = 5;
qrCodeEncoder.QRCodeVersion = 7;

qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
var pbImg = qrCodeEncoder.Encode(data, System.Text.Encoding.UTF8);
var width = pbImg.Width / 10;
var dwidth = width * 2;
Bitmap bmp = new Bitmap(pbImg.Width + dwidth, pbImg.Height + dwidth);
Graphics g = Graphics.FromImage(bmp);
var c = System.Drawing.Color.White;
g.FillRectangle(new SolidBrush(c), 0, 0, pbImg.Width + dwidth, pbImg.Height + dwidth);
g.DrawImage(pbImg, width, width);
g.Dispose();
return bmp;
}

/// <summary>
/// 调用此函数后使此两种图片合并,类似相册,有个
/// 背景图,中间贴自己的目标图片
/// </summary>
/// <param name="sourceImg">粘贴的源图片</param>
/// <param name="destImg">粘贴的目标图片</param>
public static System.Drawing.Image CombinImage(System.Drawing.Image imgBack, string destImg)
{
Image img = System.Drawing.Image.FromFile(destImg);        //照片图片
if (img.Height != 50 || img.Width != 50)
{
img = KiResizeImage(img, 50, 50, 0);
}
Graphics g = Graphics.FromImage(imgBack);

g.DrawImage(imgBack, 0, 0, imgBack.Width, imgBack.Height);      //g.DrawImage(imgBack, 0, 0, 相框宽, 相框高);

//g.FillRectangle(System.Drawing.Brushes.White, imgBack.Width / 2 - img.Width / 2 - 1, imgBack.Width / 2 - img.Width / 2 - 1,1,1);//相片四周刷一层黑色边框

//g.DrawImage(img, 照片与相框的左边距, 照片与相框的上边距, 照片宽, 照片高);

g.DrawImage(img, imgBack.Width / 2 - img.Width / 2, imgBack.Width / 2 - img.Width / 2 , img.Width, img.Height);
GC.Collect();
return imgBack;


}

///

/// Resize图片

///

/// 原始Bitmap

/// 新的宽度

/// 新的高度

/// 保留着,暂时未用

/// 处理以后的图片

public static Image KiResizeImage(Image bmp, int newW, int newH, int Mode)

{

try

{

System.Drawing.Image b = new Bitmap(newW, newH);

Graphics g = Graphics.FromImage(b);

// 插值算法的质量
g.InterpolationMode = InterpolationMode.HighQualityBicubic;

g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
g.Dispose();

return b;
}
catch
{
return null;
}


}

运行以下:

string data = "2333";
Image im0 = GCode(data);
Image im1 = CombinImage(im0 , "1.jpg");//重点所在
string filename = DateTime.Now.ToString("yyyymmddhhmmssfff").ToString() + ".jpg";
string filepath = @"./jpg/";
//如果文件夹不存在,则创建
if (!Directory.Exists(filepath))
Directory.CreateDirectory(filepath);
FileStream fs = new FileStream(filepath + filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
im1.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg); //保存图片
fs.Close();
im0.Dispose();
im1.Dispose();


委托

代码

public delegate string DelegateExam(int num);//在类外进行申明或者里面都行
private void button13_Click(object sender, EventArgs e)
{
DelegateExam de = new DelegateExam(DecD);
Console.WriteLine(de(33));//输出32
Console.WriteLine((new DelegateExam(AddD))(44));//输出45
}
private string AddD(int num)
{
return (num + 1).ToString();
}
private string DecD(int num)
{
return (num - 1).ToString();
}


匿名

Func<string, string> AA = delegate(string name)
{
name += "\nit's Nm";
return name;
};
Console.WriteLine(AA("111"));


没有委托的声明,直接用Func实现(可以查阅资料)

lamda表达式

string mid = " it's middle ";
Func<string, string> lamda = para =>
{
para += "2333";
para += mid;
return para;
};
Console.WriteLine(lamda("GRY"));


lamda是函数名,para是参数,ide可以自动识别它的类型,而且此处Func已经为他指定类型了。
=>
左边列出了其参数,右边是返回值,如果很长的话,用大括号括起来,如果不长的话,用以下方法也可以。

Func<double,double,double> Mult = (x,y) => (x*y);
Console.WriteLine(Mult(5,2));


参数用小括号括起来,右边直接写结果即可,不用大括号和return。

IComparer接口的实现

网址

线程传递参数

网址

使用ParameterizedThreadStart(不推荐,因为可以接受任何类型的数据)

//线程类的创建
public class ThreadTest
{
public static void RunTestWithPara(object data)
{
Console.WriteLine("para is {0}",data);
}
}
//按钮响应事件
private void button21_Click(object sender, EventArgs e)
{
Thread[] th = new Thread[10];
for (int i = 0; i < 10; i++)
{
th[i] = new Thread(new ParameterizedThreadStart(ThreadTest.RunTestWithPara));
}
for (int i = 0; i < 10; i++)
{
th[i].Start(i);
}
}


注意:因为是线程启动,所以不是按照严格的递增的顺序输出0~9,每次运行时的输出顺序均不相同。

LINQ表达式与lamda表达式

代码

List<string> list = new List<string>() {"list","ass","efrg","jhgkjs","jnbgt" };
var strWithJ = from a in list
where a.StartsWith("j")
orderby a ascending
select a;
foreach (var v in strWithJ)
Console.WriteLine(v);
Console.WriteLine("---------");
var strA = list.Where((a, index) => a.StartsWith("j") && index % 2 == 0);
foreach (var v in strA)
Console.WriteLine(v);


注:LINQ表达式是在每次运行foreach进行遍历时才执行搜索过程,因此执行foreach时,操作的是最新的对象。

var dd = from a in list
group a by a[0] into g
where g.Count() >= 1
select new
{
c11 = g.Key,
cnt = g.Count()
};
foreach (var ddd in dd)
{
Console.WriteLine("{0}---{1}",ddd.c11,ddd.cnt);
}
list.Add("jasld");
foreach (var ddd in dd)
{
Console.WriteLine("{0}---{1}", ddd.c11, ddd.cnt);
}


group关键词的操作

lookup和dictionary的操作

lookup只能在一开始就初始化完成,在之后不能再改变,可以是1个Key对应多个Value,可以方便得将数据分组

Dictionary只能是1个Key对应1个Value,如果冲突的话,会出现异常。

LINQ查询相关

可以实现多级嵌套查询
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: