转载农民伯伯的文章
4.2 C#点滴小技巧和小知识
在c#中,string对象的==运算已经被强行重写,它就是表示 equals,
这就是说,在c#中,实现字符串值比较的话,只需要写成"hello"==aaa就行了,
这样设计的目的是为了更直观。
----------------------------------------------------------------
如果在方法前面同时使用protected和internal来设置,那么访问将是他们的合集,即本程序集内可访问,非本程序集内但是继承了的也可以用
----------------------------------------------------------------
dll->il:ildasm test.dll /out=test.il
//中间做修改
il->dll:ilasm /dll test.il /out=test2.dll
----------------------------------------------------------------
JNBridge
----------------------------------------------------------------
WeakReference 表示弱引用,即在引用对象的同时仍然允许垃圾回收来回收该对象。
//Dictionary<K,T> 会自动维护一个空链表来保存不用的单元。
//这里,使用被缓存对象的“弱引用”,允许这些对象被垃圾回收。
private Dictionary<string, WeakReference> Buffer = new Dictionary<string, WeakReference>();
public object this[string key]
{
get{
WeakReference ret;
if (Buffer.TryGetValue(key, out ret) && ret.IsAlive) return ret.Target; else return null;
}
set{
WeakReference ret;
if (Buffer.TryGetValue(key, out ret)) ret.Target = value; else Buffer.Add(key, new WeakReference(value));
}
}
public void Remove(string key){
Buffer.Remove(key);
}
------------------------------------------------------------
如果 Hashtable 要允许并发读但只能一个线程写, 要这么创建 Hashtable 实例:
Hashtable hashtable = Hashtable.Synchronized(new Hashtable());
这样, 如果有多个线程并发的企图写 hashtable 里面的 item, 则同一时刻只能有一个线程写, 其余阻塞; 对读的线程则不受影响。
如果想锁整个 hashtable, 包括读和写, 即不允许并发的读和写, 那应该锁 hashtable 实例;
如果想允许并发的读, 不允许并发的写, 那应该创建 Synchronized 的 hashtable, 并对要加锁的一块代码用 SyncRoot 锁住, 如果不需要对一块代码加锁, 则 hashtable 会自动对单个写的操作加锁。
------------------------------------------------------------
使用 DataTable.Columns.Contains方法可以判断某个列名是否存在于某个DataTable中
DataTable t = new DataTable();
DataColumn col = new DataColumn("aaa");
t.Columns.Add(col);
col = new DataColumn("bbb");
t.Columns.Add(col);
col = new DataColumn("c");
t.Columns.Add(col);
bool b = t.Columns.Contains("bbb");
------------------------------------------------------------
1.1:System.Configuration.ConfigurationSettings.AppSettings
2.0:System.Configuration.ConfigurationManager.AppSettings
------------------------------------------------------------
ReaderWriterLockSlim
用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。
------------------------------------------------------------
C# 检查网络是否连通
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int connectionDescription, int reservedValue);
private bool IsConnected(){
int I = 0;
bool state = InternetGetConnectedState(out I, 0);
return state;
}
调用方法:
bool state = IsConnected(); //True 为连通 False 为断开
------------------------------------------------------------
尽量使用本地配置资源,比如 System.getProperty("line.separator") 代替手工输入 “\r\n”,以此解决跨平台问题(Windows、Mac等)
----------------------------------------------------------
SqlDataReader 对象可以逐行读取数据信息,但如果有10000行数据而我们只希望读取前面的100行数据,读取完后调用 SqlDataReader.Close 会非常慢。实际上调用SqlDataReader.Close 时SqlDataReader 会把后面的9900行数据全部读完才结束。
这个问题的解决办法是在SqlDataReader.Close 前调用 SqlCommand.Cancel ,取消当前命令
----------------------------------------------------------
随机数种子,用于快速生产随机数,减少随机数相同机率
方法1:new Random(Guid.NewGuid().GetHashCode())即可
方法2:
private static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
---------------------------------------------------------
浮点转整型
(int) 默认舍弃小数点后面的
Console.WriteLine(Convert.ToInt32(0.51)); // 1
Console.WriteLine((int)(0.5)); // 0
--------------------------------------------------------
如何解决winform自动缩放产生的布局问题.
将 Form 设置为this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
下边的控件都设置为
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
--------------------------------------------------------
int[,] aArray = new int[3, 3];
for (int i = 0; i < aArray.GetLength(0); i++){ //第0维的长度
for (int j = 0; j < aArray.GetLength(1); j++){
aArray[i, j]
--------------------------------------------------------
检测文件真实文件类型
读取文件的前两个字节进行判断
System.IO.FileStream fs = new System.IO.FileStream(hifile.PostedFile.FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.IO.BinaryReader r = new System.IO.BinaryReader(fs);
string fileclass = "";
byte buffer;
try{
buffer = r.ReadByte();
fileclass = buffer.ToString();
buffer = r.ReadByte();
fileclass += buffer.ToString();
}catch{ }
r.Close();
fs.Close();
if (fileclass == "255216" || fileclass == "7173")
//说明255216是jpg;7173是 gif;6677是BMP,13780是PNG;7790是exe,8297是rar
--------------------------------------------------------
DateTime dt1 = new DateTime(2008, 12, 31);
DateTime dt2 = new DateTime();
dt2 = DateTime.Now;
TimeSpan ts = new TimeSpan(dt2.Ticks - dt1.Ticks);
//相差天數(未滿一天捨去,return int type)
Response.Write(Convert.ToString( ts.Days ));
//相差天數(未滿一天亦計入,return double type)
Response.Write(Convert.ToString( ts.TotalDays ));
//相差小時數(return double type)
Response.Write(Convert.ToString( ts.TotalHours ));
//相差秒數(return double type)
Response.Write(Convert.ToString( ts.TotalMinutes ));
---------------------------------------------------------
序列号对象
[Serializeable]
[NonSerialized]
接口IDeserializationCallback
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(writer,Object);// 将对象序列号到文件
(Object)formatter.Deserialize(reader)//反序列化
---------------------------------------------------------
事件集合
EventHandlerList events = new EventHandlerList();
public event DelegateXX Event1
{
add{ events.AddHandler("Event1",value) }
remove{ events.RemoveHandler("Event1",value) }
}
events["Event1"] as DelegateXX
----------------------------------------------------------
Process 类用于代表托管进程,它实际封装了操作系统的本地进程,每一个托管进程对象都对应着操作系统真实的本地进程。
Thread类用于表示托管线程,每个托管线程都对应一个函数(“线程函数”),托管线程的执行就是线程函数代码的执行,线程函数执行完,线程也就执行完了。
Thread类与操作系统真实的本地线程不是一一对应关系,它所代表的是一个“逻辑线程”,由CLR负责创建和管理。ProcessThread类用于表示操作系统中真实的本地线程。
Win32 API SetClipboardViewer ChangeClipboardChain 可监控剪切板内容的改变,比如迅雷、电驴
FileSystemWatcher是.net提供的一个组件,可以监控特定文件夹或文件,引发对应的事件
Marshal 封送 当信息再两个进程间按照COM规范直接传送时,需要在信息的发送进程端将数据打包再发送,而接收信息的进程在收到信息后,要先解包才能得到真正的信息,这个过程就叫封送。
---------------------------------------------------------
Wtypes.h 中的非托管类型 非托管C语言类型 .NET托管类名
----------------------------------------------------
HANDLE void* System.IntPtr
BYTE unsigned char System.Byte
SHORT short System.Int16 short
WORD unsigned short System.UInt16 ushort
INT int System.Int32 int
UINT unsigned int System.UInt32 uint
LONG long System.Int32 int
BOOL long System.Int32 int
DWORD unsigned long System.UInt32 uint
ULONG unsigned long System.UInt32 uint
CHAR char System.Char
LPSTR char* System.String或System.Text.StringBuilder
LPCSTR Const char* System.String或System.Text.StringBuilder
LPWSTR wchar_t* System.String或System.Text.StringBuilder
LPCWSTR Const wchar_t* System.String或System.Text.StringBuilder
FLOAT Float System.Single
DOUBLE Double System.Double
signed char SByte sbyte
----------------------------------------------------------
new ThreadStart(delegate{ ...代码 });
Thread th1 = new Thread(new ThreadStart(方法名));
th1.Abort()// 提前中止线程
IsBackground = true //设置为背景线程 默认为false 当主线程一结束时,CLR会对属于此进程的所有背景线程调用Abort方法中止
Join可以等待子线程执行完毕
ParameterizedThreadStart 带一个参数的线程委托 也可以传一个类来实现多参数
线程优先级
Thread.Priority
Highest->AboveNormal->Normal->BelowNormal->Lowest
Lock(obj){...}
与Monitor.Enter(obj);
...
Monitor.Exit(obj); 相等
Monitor 主要用于给共享资源加锁,保证一次只有一个线程访问共享资源,且只能给引用类型的变量加锁
Mutex 可以同步值类型变量
Semaphore 用于同步多个线程访问同一类型的多个共享资源,即一次允许不超过共享资源总数的线程投入运行
EventHandle 及其子类AutoResetEvent和ManualResetEvent是最接近“交通信号灯”功能的同步方法,可用走走停停
ThreadPool 提供了有限的线程同步手段,但由于其避免了创建和销毁线程的开销,因而再性能上占优。
若要请求由线程池中的一个线程来处理工作项,请调用 QueueUserWorkItem 方法。此方法将对将被从线程池中选定的线程调用的方法或委托的引用用作参数。一个工作项排入队列后就无法再取消它。
计时器队列中的计时器以及已注册的等待操作也使用线程池。它们的回调函数也会排列到线程池。
每个进程都有一个线程池。线程池的默认大小为每个可用处理器有 25 个线程。使用 SetMaxThreads 方法可以更改线程池中的线程数。每个线程使用默认的堆栈大小并按照默认的优先级运行。
ThreadPool.SetMaxThreads(10, 200);ThreadPool.SetMinThreads(2, 40);
ReaderWriterLock 一个线程些,多个线程读(单写多读)
BackgroundWorker 非常适合再后台运行任务、前台显示结果的应用场景
RunWorkerAsync 开始
CancelAsync 中途中止 CancellatioinPending将为true
ReportProgress 报告进度
ProgressChanged 不用考虑跨线程,可直接访问可视化控件
e.ProgressPercentage //百分比
e.UserState //文字信息
Mutex m = new Mutex();多线程下保证一个数据是完整 安全的
方法1里面 m.WaitOne() ... m.ReleaseMutex();
方法2里面 m.WaitOne() ... m.ReleaseMutex();
方法3里面 m.WaitOne() ... m.ReleaseMutex();
三个方法都是多线程
Semaphore 可以一次使数个线程投入运行
构造函数 initialCount 计数器的初始值,代表空闲的共享资源数目,maximumCount 计数器最大值
执行方法中加 WaitOne Release
ManualResetEvent 红绿灯
ManualResetEvent mre = new ManualResetEvent(false);
DoWork{ mre.WaitOne(); ..打印当前线程 }
Go{ mre.Set(); ..绿灯 }
Stop{ mre.Reset(); ..红灯 }
软件启动的时候可以用这个对象,窗体启动前用WaitOne,进入Load后用 Set
线程池默认大小为可用处理器数目 乘以 25,线程池中的线程都是背景线程
----------------------------------------------------------
yyyy-MM-dd hh:mm:ss.fff
----------------------------------------------------------
#region Kill Special Excel Process
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
#endregion
Excel.Application xlApp = new Excel.Application();
.....导出excel后
if (xlApp != null)
{
int lpdwProcessId;
GetWindowThreadProcessId(new IntPtr(xlApp.Hwnd), out lpdwProcessId);
System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill();
}
------------------------------------------------------------
泛型方法中使用new()
public static IModelProvider Get<T>() where T : IModel, new()
{
new T();
string key = typeof(T).FullName;
if (!metadatas.ContainsKey(key))
metadatas.Add(key, new ModelProvider(T));
return metadatas[key];
}
------------------------------------------------------------
反射
new StackTrace().GetFrame(1).GetMethod().Name
//取得子类所有 TransactionMethodAttribute的方法
foreach (MethodInfo item in this.GetType().GetMethods())
{
object[] attrs = item.GetCustomAttributes(typeof(TransactionMethodAttribute), true);
//if (attrs.Length > 0 && attrs[0] is TransactionMethodAttribute)
}
//当前方法调用源
StackTrace trace = new StackTrace();
foreach (StackFrame frame in trace.GetFrames())
{
Console.Write(frame.GetMethod().DeclaringType.Name);
Console.Write(":\t");
Console.WriteLine(frame.GetMethod().Name);
}
------------------------------------------------------------
Name 为abc的节点 Employee结点
XmlNode emp = xmlDoc.SelectSingleNode( "/Company/Department/Employees/Employee[Name='abc']" );
ID的属性code为2的 Employee结点
XmlNode xn = xmlDoc.SelectSingleNode(@"/Company/Department/Employees/Employee/ID[@code='002']/parent::node()"
同一节点下的节点判断
Config/UserList/Group/User[Username='{0}'][Password='{1}']
-------------------------------------------------------------
属性更改
INotifyPropertyChanged
-------------------------------------------------------------
获取错误信息
innerException比Exception所包含的异常范围小
private static string BuildExceptionMessage(Exception ex)
{
StringBuilder exceptionMsgs = new StringBuilder();
while (null != ex) // this is obsolete since we're grabbing base...
{
exceptionMsgs.AppendFormat("\n{0}\n{1}\n{2} Soure:{3}", ex.GetType().Name, ex.Message,ex.StackTrace,ex.Source);
ex = ex.InnerException;
//e.TargetSite 引发此错误的方法
}
return exceptionMsgs.ToString();
}
--------------------------------------------------------------
C# 基础
值类型(value type) 有与其对应的默认值 永远不能为null
引用类型(reference type) 默认值 null 表示没有指定任何已分配内存的地址
--------------------------------------------------------------
检测回车
e.KeyCode == Keys.Enter
--------------------------------------------------------------
关闭进程最好不要用kill
Processpro = new Process();
pro.Start();
pro.CloseMainWindow();
---------------------------------------------------------------
C# 查找字符串中出现的子串 "abcdef".Contains("abc") 这样就不用IndexOf
---------------------------------------------------------------
C# 打开窗口
Process.Start("main.cpl"); //打开鼠标设置窗口
Process.Start("desk.cpl"); //打开桌面设置窗口
Process.Start("ncpa.cpl"); //打开网络连接窗口
Process.Start("mmsys.cpl"); //打开声音设置窗口
Process.Start("IExplore.exe","www.g.cn");
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized; //启动后最小化
startInfo.Arguments = "www.sina.com.cn"//自动访问新浪网
Process.Start(startInfo);
startInfo.Verbs 遍历谓词 比如文本文件就有open、print、printto 默认为open,即默认双击文本文件为打开操作
CloseMainWindow() 不会强制应用程序立即退出,相当于用户直接点击主窗体上的“关闭”按钮,该方法为非阻塞调用。
Kill()直接结束进程,不会保存数据
---------------------------------------------------------------
C# 调用cmd程序
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine(@"netstat -a -n > c:\port.txt");
---------------------------------------------------------------
C# 中各种Lock的速度比较
Interlocked可以直接编译为CPU指令,速度最快,虽然功能较少但能用则用。
Interlocked.Increment(ref seed);
CriticalSection(也就是lock关键字或者 Monitor.Enter()方法)仅比Interlocked慢,建议使用。
对于ReaderWriterLock和 ReaderWriterLockSlim,Slim快近一倍,但缺点是不能track owner,也就是同一线程不能多次进入同一个lock。Reader比Writer要慢,估计是要维护reader count的原因。
ReaderWriterLock
Mutex,Semaphore,Event即使可以获得lock也要进入内核模式,所以最慢,要尽量避免使用。
---------------------------------------------------------------
文件遍历
foreach (FileInfo file in new DirectoryInfo(rootName).GetFiles("*.264",SearchOption.AllDirectories))
{
dict.Add(file.FullName, file.LastWriteTime);
}
-------------------------------------------------------------
指定同时只能由一个线程执行该方法。静态方法锁定类型,而实例方法锁定实例。
[MethodImpl(MethodImplOptions.Synchronized)]
-------------------------------------------------------------
数字格式化
【<%#Container.DataItem("price")%>的结果是500.0000,怎样格式化为500.00?】
int i=123456;
string s=i.ToString("###,###.00");
--------------------------------------------------------------
[Conditional("DEBUG")]
--------------------------------------------------------------
修改VS2005模板
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplatesCache\Web\CSharp\2052\
----------------------------------------------------------
格式化百分比
ToString("0%")
ToString("0.00%")
ToString("p")