C#中的’?号’及用法

1. 可空类型修饰符(?):

  引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空。
  例如:
    string str=null;是正确的。
    int i=null;编译器将报错。
    为了使值类型也可为空,可空类型出现了,可空类型使用可空类型修饰符?来表示,表现形式为T?。
  例:int?表示是可空的整形,DateTime?表示为可空的时间。
  T?其实是System.Nullable<T>(泛型结构)的缩写形式,也就意味着当你用到T?时编译器在编译时会把T?编译成System.Nullable<T>的形式,
  例如:int?,编译后便是System.Nullable<int>的形式。

2. 三元(运算符)表达式(?:):

语法为:条件表达式?表达式1:表达式2;
该操作首先求出条件表达式的值(bool类型),为true时调用表达式1,为flase时调用表达式2。
其逻辑为:"如果为真执行第一个,否则执行第二个。"

 例:
 test ? expression1 : expression2
 test 任何 Boolean 表达式。
 expression1 test 为 true 时返回的表达式。可能是逗点表达式。
 expression2 test 为 false 时返回的表达式。可能是逗点表达式。

 例如:
 string prm1="4"; string prm2="5";
 string prm3 = prm1==prm2?"yes":"no" // 此时prm3值为"no".

3. 空合并运算符(??):

空合并运算符 (null coalescing operator) ??
  用于定义可空类型和引用类型的默认值。如果此运算符的左操作数不为 null,则此运算符将返回左操作数;否则返回右操作数。
  例:a??b 如果 a 为非空,则 a ?? b 的结果为 a;否则结果为 b 。

空合并运算符为右结合运算符,即操作时从右向左进行组合的。
  例:“a??b??c”的形式按“a??(b??c)”计算。

 

Json.NET 反序列化 多层次 泛型 复杂对象 json(如List)到数据实体对象

做了一天有关于JSON的工作,解析为JSON难度到不大,用.Net中微软自己的方法也很好用。

多层次泛型复杂对象(不是简单的 List<T> 而是  List<<List<T>>>)到数据实体对象,花了大半天时间从下午到晚上,一直研究到快凌晨。。。

最后还是放弃微软的方法。使用了 Json.NET 的 Newtonsoft.Json.dll 来反序列化。

 

随便推荐一个网站: 在线JSON校验格式化工具(K JSON) – json解析,json格式化,json 在线校验  http://www.kjson.com/

可以把要反解析的json放进去效验一下,避免错误格式,比如我今天遇到几次收到的 json 压根就是格式不正确的json … 非常耽误时间

 

下面给个例子供参考:

( 例子是在Handler1.ashx中做的,首先引用 “using Newtonsoft.Json;”)

using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using Newtonsoft.Json;

namespace WebApp1
{
    /// <summary>
    /// Handler1 的摘要说明
    /// </summary>
    public class Handler1 : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            string strJson = @"{
                                    'success': true,
                                    'Object': {
                                        'ID': -1,
                                        'MoveID': 'D09-242',
                                        'EX_Unit': 00,
                                        'In_Unit': 00,
                                        'Remark': 'OK',
                                        'Detail': [
                                            {
                                                'ID': 1,
                                                'M_ID': null,
                                                'DVID': '11',
                                                'DVName': 'aa0',
                                                'DVType': null
                                            },
                                            {
                                                'ID': 2,
                                                'M_ID': null,
                                                'DVID': '22',
                                                'DVName': 'aa1',
                                                'DVType': null
                                            },
                                            {
                                                'ID': 3,
                                                'M_ID': null,
                                                'DVID': '33',
                                                'DVName': 'aa2',
                                                'DVType': null
                                            }
                                        ]
                                    },
                                    'msg': '成功'
                                }";
            ///大{}内 JSONObject 数据, 最外层
            JSONObject<MoveInfo<MoveDetailInfo>> obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JSONObject<MoveInfo<MoveDetailInfo>>>(strJson);
            string msg = obj.msg;
            string success = obj.success.ToString();

            ///'Object'是实体对象类"MoveInfo"的实体类的数据
            MoveInfo<MoveDetailInfo> info = obj.Object;
            int Mv_id1 = info.ID;   //可以直接赋值给MoveInfo的对象获取到值
            int Mv_id2 = obj.Object.ID; //还可以用上层的Object.ID获取到值

            ///info.Detail 或 obj.Object.Detail 都是实体对象类"MoveDetailInfo"的实体类的数据
            string DVName1 = "";
            string DVName2 = "";
            string DVName3 = "";

            DVName1 = obj.Object.Detail[0].DVName;      //方法1: 从最上次对象实体中取子属性

            foreach(MoveDetailInfo mvinfo in info.Detail)
                DVName2 += mvinfo.DVName;       //方法2: 迭代上层 info.Detail 对象"MoveDetailInfo"获取属性

            MoveDetailInfo dvinfo =  info.Detail[0];
            DVName3 = dvinfo.DVName;        //方法3: 再赋值给MoveDetailInfo对象类后获取

            context.Response.ContentType = "text/plain";
            context.Response.Write(string.Format("0;{0}\r1:{1};\r2:{2};", DVName1, DVName2, DVName3));
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

    public class JSONObject<T>
    {
        private bool _success;
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool success
        {
            get { return _success; }
            set { _success = value; }
        }

        private T _Object;
        /// <summary>
        /// 业务实体对象
        /// </summary>
        public T Object
        {
            get { return _Object; }
            set { _Object = value; }
        }

        private string _msg;
        /// <summary>
        /// 消息
        /// </summary>
        public string msg
        {
            get { return _msg; }
            set { _msg = value; }
        }
    }

    /// <summary>
    /// MoveInfo 调拨单
    /// </summary>
    public class MoveInfo<T>
    {
        private int _ID;
        public int ID
        {
            get { return _ID; }
            set { _ID = value; }
        }

        private string _MoveID;
        public string MoveID
        {
            get { return _MoveID; }
            set { _MoveID = value; }
        }

        private int _EX_Unit;
        public int EX_Unit
        {
            get { return _EX_Unit; }
            set { _EX_Unit = value; }
        }

        private int _In_Unit;
        public int In_Unit
        {
            get { return _In_Unit; }
            set { _In_Unit = value; }
        }

        private List<MoveDetailInfo> _Detail;
        public List<MoveDetailInfo> Detail
        {
            get { return _Detail; }
            set { _Detail = value; }
        }
    }

    /// <summary>
    /// 调拨明细信息
    /// </summary>
    public class MoveDetailInfo
    {
        private int _ID;
        public int ID
        {
            get { return _ID; }
            set { _ID = value; }
        }

        private string _M_ID;
        public string M_ID
        {
            get { return _M_ID; }
            set { _M_ID = value; }
        }

        private string _DVID;
        public string DVID
        {
            get { return _DVID; }
            set { _DVID = value; }
        }

        private string _DVName;
        public string DVName
        {
            get { return _DVName; }
            set { _DVName = value; }
        }

        private string _DVType;
        public string DVType
        {
            get { return _DVType; }
            set { _DVType = value; }
        }
    }
}

 

参考文章 :

.net泛型在序列化、反序列化JSON数据中的应用  http://www.cnblogs.com/jdmei520/archive/2009/09/19/1569600.html

C# 将javascript的JSON反序列化为数组,泛型List,对象  –  http://hi.baidu.com/jiang_yy_jiang/item/c32aff05bcce12ca915718e8

 

 

C# 中的 Json

一直是做的winform多一些, 可最近做的活儿都是常用JSON。

项目的服务交互是 jquery easyui , Handler.ashx做的, 后台是工具配置的数据.

 

fastJSON -> fastJSON.dll

Json.NET -> Newtonsoft.Json.dll

DataContractJsonSerializer -> System.Runtime.Serialization.Json

速度上对比:
fastJSON  > Json.NET > Windows.Data.Json 
参考:
http://james.newtonking.com/json/help/html/JsonNetVsDotNetSerializers.htm
http://james.newtonking.com/json/help/html/JsonNetVsWindowsDataJson.htm

C#、PHP、Python 运算符的优先级

C#、PHP、Python 运算符的优先级

C#  运算符优先级

优先级
类别
运算符
1
基本
(x) x.y f(x) a[x] x++ x――new typeof sizeof checked unchecked
2
单目
+ - ! ~ ++x ――x (T)x
3
乘法与除法
* / %
4
加法与减法
+ -
5
移位运算
<< >>
6
关系运算
< > < = >=
7
条件等
= = ! =
8
位逻辑与
&
9
位逻辑异或
^
10
位逻辑或
|
11
条件与
&&
12
条件或
13
条件
?:
14
赋值
= *= /= %= += -= <<= >>= &= ^= |=

 

上表源自:  http://baike.baidu.com/view/262524.htm#4

C# 提供大量运算符,这些运算符是指定在表达式中执行哪些操作的符号。             ==, !=, &lt;, &gt;, &lt;=, &gt;=, binary +, binary -, ^, &amp;,’ xml:space=”preserve”>整型运算包括 ==、!=、<、>、<=、>=、binary +、binary -、^、& |~, ++, –, and sizeof() are generally allowed on enumerations.’ xml:space=”preserve”>、~、++、– 和 sizeof(),通常在枚举时允许这些运算。  overloaded by the user, thus changing their meaning when applied to a user-defined type.’ xml:space=”preserve”>此外,很多运算符可被用户重载,由此在应用到用户定义的类型时更改这些运算符的含义。

下表列出了按发型版本不同的 C# 运算符:

 

PHP运算符优先级

 

 
结合方向 运算符 附加信息
非结合 clone new clone 和 new
[ array()
非结合 ++ -- 递增/递减运算符
非结合 ~ - (int) (float) (string) (array) (object) (bool) @ 类型
非结合 instanceof 类型
右结合 ! 逻辑操作符
* / % 算术运算符
+ - . 算术运算符 和 字符串运算符
<< >> 位运算符
非结合 < <= > >= <> 比较运算符
非结合 == != === !== 比较运算符
& 位运算符 和 引用
^ 位运算符
| 位运算符
&& 逻辑运算符
|| 逻辑运算符
? : 三元运算符
= += -= *= /= .= %= &= |= ^= <<= >>= 赋值运算符
and 逻辑运算符
xor 逻辑运算符
or 逻辑运算符
, 多处用到

 

 

Python 运算符优先级

 

这个表给出Python的运算符优先级(从低到高).

从最低的优先级(最松散地结合)到最高的优先级(最紧密地结合)。

这意味着在一个表达式中,Python会首先计算表中较下面的运算符,然后在计算列在表上部的运算符。

 
运算符 描述
lambda Lambda表达式
or 布尔“或”
and 布尔“与”
not x 布尔“非”
in,not in 成员测试
is,is not 同一性测试
<,<=,>,>=,!=,== 比较
| 按位或
^ 按位异或
& 按位与
<<,>> 移位
+,- 加法与减法
*,/,% 乘法、除法与取余
+x,-x 正负号
~x 按位翻转
** 指数
x.attribute 属性参考
x[index] 下标
x[index:index] 寻址段
f(arguments...) 函数调用
(experession,...) 绑定或元组显示
[expression,...] 列表显示
{key:datum,...} 字典显示
'expression,...' 字符串转换

 

上两表源自:  http://tool.oschina.net/commons?type=6#php_

 

C#中用正则表达式取页面下拉菜单(select)中的值

 

给几个在C#中,使用正则表达式取页面下拉菜单(select)中的值示例:

//取html中全部 select 的 name
Regex reg_name = new Regex(@"(?<=<select name=\"").*?(?=\"")");

//取html中全部<select>项的值
Regex reg_select = new Regex("(?is)<select name=*.*?>]*.*?</select>");

//取html中一个 select name 等于"Status"的值
Regex status = new Regex(@"(?is)<select name=\""status\"">]*.*?</select>");

 

一下是一段完整的代码和方法,取html中一个下拉菜单 select name 等于”Status”的中值,添加到DropDownList中:

        string strDoc = (你的html);

        //取html中一个下拉菜单 select name 等于"Status"的中值
        Regex status = new Regex(@"(?is)<select name=\""status\"">]*.*?</select>");
        MatchCollection mc_status = status.Matches(strDoc);
        getSelectOptions(mc_status, cmbStatus);

        /// <summary>
        /// 取select对列表复制
        /// </summary>
        /// <param name="selected"></param>
        /// <param name="cmb"></param>
        void getSelectOptions(MatchCollection selected, ComboBox cmb)
        {
            if (selected.Count < 1)
                return;
            txtValues.Text = "";
            txtValues.Text = selected[0].Value.Replace("</option>", Environment.NewLine);
            string tmpTxt = "";
            foreach (string s in txtValues.Lines)
            {
                if (s == "")
                    continue;
                string a = "";
                a = s.Replace("\"", "").Replace("<option value=\"", "");
                int x = a.LastIndexOf(">");
                tmpTxt += a.Substring(x + 1) + Environment.NewLine;
            }
            txtValues.Text = tmpTxt.Trim();
            cmb.Items.Clear();
            cmb.Items.AddRange(txtValues.Lines);
            cmb.SelectedIndex = 0;
            cmb.Size = cmb.PreferredSize;
        }

 

推荐一个正则表达式测试/验证工具 – http://bohu.net/blog/8814

 

推荐一个正则表达式测试/验证工具

这几天代码里用到很多正则表达式,需要验证,直接在程序里调试太麻烦。

比如:C#中用正则表达式取页面下拉菜单(select)中的值 – http://bohu.net/blog/8815

找到了这个验证工具:

正则表达式测试器 – http://deerchao.net/tools/regex_tester/index.htm
说明:该工具允许你测试和分析正则表达式。

解决 webBrowser DocumentCompleted 的多次调用

winform中使用webBrowser抽取页面中的一些数据。断点“webBrowser1_DocumentCompleted”发现,跑进来了好多次。

DocumentCompleted执行多次,跟踪发现ReadyState状态不一样,分别是Intercative和Complete。

而MSDN对这两种状态值的解释是:

  • Complete该控件已完成新文档及其所有内容的加载;
  • Interactive该控件已经加载足够的文档以允许有限的用户交互,比如单击已显示的超链接。

增加判断“ReadyState”之后继续,DocumentCompleted仍然执行了两次,但ReadyState状态一样都是Complete。再查原因。

MSDN对其解释是在多个的帧的情况下DocumentComplete获取触发多次。并非每个框架将触发此事件,但触发DownloadBegin事件的每个框架将触发相应的DocumentComplete事件。

 

最后webBrowser1_DocumentCompleted中的代码是:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            string BrowserUrl = webBrowser1.Url.ToString();

            if (String.IsNullOrEmpty(BrowserUrl)) //检查未赋值或空值
                return;
            if (BrowserUrl.Equals("about:blank")) //是否为空白页
                return;
            if (webBrowser1.ReadyState != WebBrowserReadyState.Complete)  //状态为完成
                return;
            if (e.Url.ToString() != BrowserUrl)  //检查事件url和webBrowser的url
                return;
            if (webBrowser1.DocumentText == "")
                return;

            ... ...
        }

 

还有一点,就是窗体打开就加载webBrowser1,如放在 Form_Load 会使程序界面加载很慢,建议放在 Form_Shown中(每当窗体第一次显示时发生)。

 

C# 多线程操作整理 (System.Threading)

Thread 类

创建并控制线程,设置其优先级并获取其状态。

命名空间:System.Threading 程序集:mscorlib(在 mscorlib.dll 中)

概述与概念

C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。

1.使用线程的情况

  • ①.程序需要执行和两个和多个任务
  • ②.程序要等待某事件的发生:例如用户输入、文件操作、网络操作和搜索
  • ③.后台程序

2.多线程的并发执行 如果有多个线程在执行,单CPU只有一个,到底执行的哪个?

  • ①.如果一个线程连续占用CPU资源时间过长,其它的资源得不到执行,      则系统会强制的切换执行其它线程。(强制剥夺)
  • ②.如果一个线程没事可做、CPU可执行其它线程。(主动放弃)
  • ③.这是由操作系统的调度机制决定的,不同的操作系统调度机制不一样。    一般无法精确的预料多线程的执行顺序,在程序设计的时候应特别注意

3.创建并启动线程

ThreadStart 线程启动委托名=new ThreadStart(方法名);

Thread 线程实例名=new Thread(线程启动委托名); 线程实例名.Start();

4.终止线程

  • ①.线程实例名.Abort();用此方法的后果是不可恢复的终止线程。
  • ②.线程实例名.Interrupt();中断后可恢复

5.休眠线程

  • ①.线程实例名.Sleep();     当线程Sleep时,系统就立即退出执行队列一段时间,当睡眠结束时,系统会产生一个时钟中断,从而     使线程回到执行队列中,从而恢复线程的执行。

6.挂起/恢复线程

  • ①.线程实例名.Suspend();挂起     与线程休眠不同,线程的挂起不会使线程立即停止执行,直到线程到达安全点之后它才可以将该线程挂起,如果线程尚未启动或已经停止,则它将不能挂起。
  • ②.线程实例名.Resume();恢复      将使一个线程跳出挂起状态并使该线程继续执行。     一个线程不能对另一个线程调用Sleep() ,但是一个线程可以对另一个线程调用Suspend()。     还可以使用许多其它的方式来阻塞线程。例如,可以通过调用 Thread.Join 使一个线程等待另一个线程 (子线程)停止。使用Monitor.Wait使一个线程等待访问一个同步对象。

7.串行化线程

  • ①.线程实例名.jion();     例如在主线程中插入t.jion();      主线程执行到这条语句后,主线程(当前线程)立即进入阻塞状态.直到t运行完后阻塞状态才解除。相当于把t的任务插入或串联到主线程中,把两条线索串联成一条线索

8.线程的锁定机制 线程的锁定机制可以保证每次只有一个线程可以访问共享资源。 使用关键字lock

  • ①.lock语句的语法      lock(对象引用)语句块;
  • ②.lock语句的功能      当对象被lock 锁定时,访问该线程的其它线程会进入等待的状态。
  • ③.对象锁机制保证了对象访问的完整性:只有一个线程完成操作后,其它的线程才能进行操作。
  • ④.一般情况下,当一个线程写某个变量,而同时可能有其它的线程读或写这个变量时,为了保持数据的一 致性应该使用锁定机制。
  • ⑤.线程的安全性      线程安全性就是保护的类的成员和代码的安全,从而使他们不会同时被几个线程中断,使用锁定机制。
  • ⑥.多线程公用一个对象时,就不应该使用lock关键字了,这里Monitor,Monitor提供了使线程共享资源的方 案。 Monitor类可以锁定一个对象,一个线程只有得到这把锁才可以对该对象进行操作。 如: Monitor.Enter(obj);
    Monitor.Exit(obj);
  • ⑦.临界区和锁 当谈论多线程应用程序的时候,首先应该想到的就是并发性问题。尽管这对于同时执行多个任务的程序是很有用的,但通常都是危险的。为了解决这个问题,在C#中提出了临界区和锁的概念。在程序设计中,临界区是一块在任何时候只能有一个进程进入的区域。在C#中通过语句lock来声明临界区。lock声明后面的代码,不管是以行还是一块代码,在同一时间最多只能有一个进程执行。

9.线程的优先级具有不可靠性,就是说不能用优先级来控制线程的执行顺序。

10.后台线程

  • ①.什么是后台线程?比起应用程序的主图形用户界面(GUI)线程来说,这些线程以较低的优先权在不同的过程中运行着。对于不能立即执行结束, 又不想一直等待的任务,后台线程能很好的胜任。在C#中,把线程对象的  IsBackground属性设为true,该线程即为后台线程。    后台线程跟前台线程只有一个区别,那就是后台线程不妨碍程序的终止。一旦一个进程所有的前台线程都终止后,CLR将通过调用任意一个存活中的后台进程的Abort()方法来彻底终止进程。注意:后台线程不能直接操作所在进程之外的数据引用。
  • ②.怎样与后台线程通讯?运用MethodInvoker委派实体。也可在初始化(构造函数)中加入下面一句即可实现通讯:

Control.CheckForIllegalCrossThreadCalls = False;

要使用MethodInvoker委派,需要三个条件:

  •   a.一个创建委派的后台线程
Thread thread=new Thread(new ThreadStart(Run));

thread.IsBackground=true;  //把Thread设为后台线程

thread.Start();
  •   b.一个用作后台线程与前台可视化单元的接口的类级方法
 public void Run()
        {
            int count = 0;
            try
            {
                MethodInvoker mi = new MethodInvoker(this.UpdateLabel);
                //创建一个委托,UpdateLabel是该委托所托管的代码,必须是声明为void 且不接受任何参数的任何方法。
                while (true)
                {
                    count++;
                    //this.Invoke(mi);//同步执行委托
                    this.BeginInvoke(mi);//异步执行委托
                    Thread.Sleep(500);
                }
            }
            catch (ThreadInterruptedException e)
            {
                Console.WriteLine("Interruption Exception in Thread:{0}", e);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in Thread:{0}", ex);
            }
        }
  •   c.一个应用程序中可以更新的可视化单元
public void UpdateLabel()
{     
    label1.Text=count.ToString();   
}

Excel 数字列名(序号)与字母列名(序号)的转换

2012年2月6日作者:enet

 

来自: http://www.tal-rasha.com/archives/254.html
写代码使用到的Excel索引间的转换,其实就是十进制和二十六进制间的转换

        /// <summary>
        /// 用于excel表格中字母转成索引,从1对应A开始
        /// </summary>
        /// <param name="column">号</param>
        /// <returns>索引</returns>
        private int ColumnToIndex(string column)
        {
            if (!Regex.IsMatch(column.ToUpper(), @"[A-Z]+"))
            {
                throw new Exception("Invalid parameter");
            }
            int index = 0;
            char[] chars = column.ToUpper().ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                index += ((int)chars[i] - (int)'A' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
            }
            return index;
        }

        /// <summary>
        /// 用于将excel表格中索引转成字母,从A对应1开始
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>号</returns>
        private string IndexToColumn(int index)
        {
            if (index <= 0)
            {
                throw new Exception("Invalid parameter");
            }
            index--;
            string column = string.Empty;
            do
            {
                if (column.Length > 0)
                { index--;
                }
                column = ((char)(index % 26 + (int)'A')).ToString() + column;
                index = (int)((index - index % 26) / 26);
            } while (index > 0);
            return column;
        }