e.g float a=1.3; 会编译报错,正确的写法 float a = (float)1.3;或者float a = 1.3f;(f或F都可以不区分大小写)
1.java中3*0.1==0.3将会返回什么?true还是false?
fale,因为浮点数不能完全精确的表示出来,一般会损失精度。
2.java中float f = 3.4;是否正确?
不正确,3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于向下转型会造 成精度损失,因此需要强制类型转换float f = (float)3.4;或者写成 float f = 3.4f;才可以。
PropertyInfo 首先是用在实体类上的,获取实体类上的公开属性,或者是泛型T类型。一般做转换用,可以从Dictionary,SqlDataReader动态转换为具体实体
程序中用颜色表示的代码
Color.FromArgb(0, 0, 0);
Color.White;
Color c= Color.FromName("#00FF00");
知识点
DataTable转换为集合
public List FillModel(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0)
{
return null;
}
List modelList = new List();
foreach (DataRow dr in dt.Rows)
{
//T model = (T)Activator.CreateInstance(typeof(T));
T model = new T();
for (int i = 0; i < dr.Table.Columns.Count; i++)
{
PropertyInfo propertyInfo = model.GetType().GetProperty(dr.Table.Columns[i].ColumnName);
if (propertyInfo != null && dr[i] != DBNull.Value)
propertyInfo.SetValue(model, dr[i], null);
}
modelList.Add(model);
}
return modelList;
}
知识点
委托和事件简介
1.委托是有签名的,事件没有,他由委托定义
2.委托定义public delegate void MyEventHandler(object sender, MyEventArgs e);
3.事件定义private event MyEventHandler myevent;
4.事件处理函数一般起名On....
坑
创建随机函数Random对象 一定要放在循环外面
在循环内容使用时,可以用random.next() 方法。如果直接在循环内使用New Random().Next(1,100)每次生成的随机数是相同的
知识点
枚举类型和值的转换
枚举类型和它对应的值可以直接通过强制类型转换获取,比如定义枚举类型
enum FileType
{
Increase=1,
Covered=2
}
由数值转换为枚举(FileType)2;由枚举转换为数值(int)FileType.Increase;枚举类型还可以调用GetHashCode方法返回值类型
知识点
实例化委托的三种方法
1.声明委托,声明函数,把函数入口给委托
声明委托:delegate int MathHandler(int num)
声明函数:public int methord(int num){return num *2;}
把函数入口给委托变量: MathHandler handler=methord;
注意委托是类型,不是变量,要使用应该是MathHandler handler;
2.匿名委托,实例化委托实例
MathHandler handler=delegate(int num){return num*2;}
3.lambda表达式实例化委托
MathHandler handler= number=>number *2;
系统中预定义的几个委托类型:
Func,Action, delegate bool System.Predicate(T obj)
知识点
方法参数中的this/扩展方法
这种用法说明该方法是扩展方法!这个扩展方法在静态类中声明,定义一个静态方法
第一个参数定义它的扩展类型,后面如果有参数,则代表调用时的参数
如下定义:
public static class MyWayClass
{
public static void MyWay(this string str)
{
Console.WriteLine("hi");
}
}
该定义扩展了String类,为它增加了MyWay方法,调用时它没有参数
string str = "sss";
str.MyWay();//输出hi
那如何为它指定参数呢,就是在定义MyWay方法中再增加一个参数如:
public static class MyWayClass
{
public static void MyWay(this string str,string s1)
{
Console.WriteLine(s1);
}
}
则调用时, string str = "sss";
str.MyWay(str); //输出sss
可以看到,最外面的静态类可以随便指定,关键字this后的类型就是要扩展的类型,该方法就是扩展的方法。
知识点
Enumerable.Repeat 用法
定义:
IEnumerable Enumerable.Repeat(TResult element,int count)
作用:把当前element类复制count份(数据完全相同),放到一个集合中
e.g : var list=Enumerable.Repeat(myClass,2);
注意:复制出来的对象指向原有的对象,所以该对象如果修改则原有对象也会修改,复制多份也是一样的
知识点
字符串比较不区分大小写
使用到了StringComparison.OrdinalIgnoreCase
e.g
string a = "123Abc";
string b = "123abc";
bool flag= a.Equals(b,StringComparison.OrdinalIgnoreCase);
输出:true
知识点
C#中的多态
1.父级方法必须为virtual否则子集也没法重写。
2.如果用子集给父级赋值,子集中override的方法可以重写父级。
3.如果子集中有父级重名方法,则会隐藏子集实现,只展示父级方法(版本控制),或在子集方法中使用new 关键字主动隐藏子集方法
e.g
public class ClassA
{
public virtual void Eat()
{
Console.WriteLine("A Eat");
}
}
public class ClassB:ClassA
{
public void Eat()
{
Console.WriteLine("B Eat");
}
public void TestB()
{
}
}
如果 赋值 ClassA model=new ClassB();
model 中则没有TestB方法,访问Eat方法时,调用的是ClassA的Eat。如果ClassB中 这样:public void override Eat() 则调用的是ClassB中的方法
当再把model对象转为ClassB时,(ClassB)model 则可以访问TestB方法,Eat方法也是ClassB的了
知识点
Thread.Join方法的使用 线程间的同步
方法说明:调用Join方法的线程,阻塞当前线程,直到调用Join方法的线程执行完毕,再执行当前线程。(可以理解为调用Join方法的线程加塞,先执行完我,再执行别的)
重载版本public bool Thread.Join(Int millisecondsTimeout)
方法说明:先阻塞一段时间(millisecondsTimeout),然后在调用Join方法的线程,阻塞当前线程。
如果在阻塞millisecondsTimeout时间内,调用Join方法的线程完成了,则立即返回true,不再等millisecondsTimeout
如果在阻塞millisecondsTimeout时间内,调用Join方法的线程未完成,则立即返回false
e.g
public class ThreadJoin_Bll
{
static Thread thread1, thread2;
public void Go()
{
thread1 = new Thread(ThreadProc);
thread1.Name = "Thread1";
thread1.Start();
thread2 = new Thread(ThreadProc);
thread2.Name = "Thread2";
thread2.Start();
}
private static void ThreadProc()
{
Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
if (Thread.CurrentThread.Name == "Thread1" &&
thread2.ThreadState != ThreadState.Unstarted)
{
Console.WriteLine("\n thread1 State:{0}, thread2 State: {1}",thread1.ThreadState, thread2.ThreadState);
// thread2.Join(5000);
if (thread2.Join(2000))
Console.WriteLine("Thread2 has termminated.");
else
Console.WriteLine("The timeout has elapsed and Thread1 will resume.");
Console.WriteLine("\ncurrent thread:{0}", Thread.CurrentThread.Name);
}
if (Thread.CurrentThread.Name == "Thread2")
{
Thread.Sleep(3000);
}
Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
Console.WriteLine("Thread1: {0}", thread1.ThreadState);
Console.WriteLine("Thread2: {0}\n", thread2.ThreadState);
}
}
知识点
ManualResetEvent类的使用 线程间的同步、控制
类说明:构造函数中必须传一个Bool的参数,true:终止,默认不阻塞;false:非终止,默认阻塞。该类控制多个线程的阻塞与执行。
如调用Set方法,会将所有调用waitOne的线程设置为非阻塞。
e.g
public class ManualResetEvent_Bll
{
ManualResetEvent mre = new ManualResetEvent(false);
public void Go()
{
for (int i = 0; i < 3; i++)
{
Thread t = new Thread(MyPro);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" +
"\nto release all the threads.\n");
Console.ReadLine();
mre.Set();
Thread.Sleep(500);
Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +
"\ndo not block. Press Enter to show this.\n");
Console.ReadLine();
for (int i = 3; i <= 4; i++)
{
Thread t = new Thread(MyPro);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(500);
Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +
"\nwhen they call WaitOne().\n");
Console.ReadLine();
mre.Reset();
Thread t5 = new Thread(MyPro);
t5.Name = "Thread_5";
t5.Start();
Thread.Sleep(500);
Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");
Console.ReadLine();
mre.Set();
}
void MyPro()
{
string name = Thread.CurrentThread.Name;
Console.WriteLine(name + " start and call waitOne method!");
mre.WaitOne();
Console.WriteLine(name + " ends ");
}
}
知识点
AutoResetEvent类的使用 线程间的同步、控制
类说明:构造函数中必须传一个Bool的参数,true:终止,默认不阻塞;false:非终止,默认阻塞。该类控制单个线程的阻塞与执行。
如调用Set方法,会将所有调用waitOne的线程中的一个设置为非阻塞;如想释放所有线程,则需多次调用Set方法。
e.g
public class AutoResetEvent_Bll
{
AutoResetEvent event_1 = new AutoResetEvent(true);
AutoResetEvent event_2 = new AutoResetEvent(false);
public void Go()
{
for (int i = 1; i < 4; i++)
{
Thread t = new Thread(Mypro);
t.Name = "Thread_" + i;
t.Start();
}
Thread.Sleep(250);
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Press Enter to release another thread.");
Console.ReadLine();
event_1.Set();
Thread.Sleep(250);
}
Console.WriteLine("\r\nAll threads are now waiting on AutoResetEvent #2.");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Press Enter to release a thread.");
Console.ReadLine();
event_2.Set();
Thread.Sleep(250);
}
}
private void Mypro()
{
string name = Thread.CurrentThread.Name;
Console.WriteLine("{0} waits on AutoResetEvent #1.", name);
event_1.WaitOne();
Console.WriteLine("{0} is released from AutoResetEvent #1.", name);
Console.WriteLine("{0} waits on AutoResetEvent #2.", name);
event_2.WaitOne();
Console.WriteLine("{0} is released from AutoResetEvent #2.", name);
Console.WriteLine("{0} ends.", name);
}
}
知识点
EventWaitHandle类的使用 线程间的同步、控制
类说明:该类是AutoResetEvent和ManualResetEvent 类的父类,它实现了Set,ReSet方法,用法和两个子类相同,可以考虑多态
构造函数稍不同:EventWaitHandle myH = new EventWaitHandle(false, EventResetMode.ManualReset);
知识点
WaitHandle类的使用 多线程间的同步、控制
类说明:该类是EventWaitHandle类的父类,它实现了静态方法WaitAll、WaitAny、SignalAndWait,虚方法WaitOne
可以看到WaitHandle的一些方法,它就是用来控制多个EventWaitHandl或其子类的多个线程的同步状态的
e.g
public class WaitHandler_Bll
{
// Define an array with two AutoResetEvent WaitHandles.
WaitHandle[] waitHandles = new WaitHandle[]
{
new AutoResetEvent(false),
new AutoResetEvent(false)
};
Random r = new Random();
public void Go()
{
// Queue up two tasks on two different threads;
// wait until all tasks are completed.
DateTime dt = DateTime.Now;
Console.WriteLine("Main thread is waiting for BOTH tasks to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
WaitHandle.WaitAll(waitHandles);
// The time shown below should match the longest task.
Console.WriteLine("Both tasks are completed (time waited={0})",
(DateTime.Now - dt).TotalMilliseconds);
// Queue up two tasks on two different threads;
// wait until any tasks are completed.
dt = DateTime.Now;
Console.WriteLine();
Console.WriteLine("The main thread is waiting for either task to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
int index = WaitHandle.WaitAny(waitHandles);
// The time shown below should match the shortest task.
Console.WriteLine("Task {0} finished first (time waited={1}).",
index + 1, (DateTime.Now - dt).TotalMilliseconds);
}
private void DoTask(Object state)
{
AutoResetEvent are = (AutoResetEvent)state;
int time = 1000 * r.Next(2, 10);
Console.WriteLine("Performing a task for {0} milliseconds.", time);
Thread.Sleep(time);
are.Set();
}
}
知识点
WaitHandle.WaitOne函数
其中一个版本:public virtual bool WaitOne(int millisecondsTimeout);
说明:先等待millisecondsTimeout秒后,执行WaitOne函数。如果等待millisecondsTimeout期间有调用set方法,则直接返回true;否则,当时间到后,返回false
知识点
WaitHandle.WaitAny函数
其中一个版本:public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout); 注意返回的是int
说明:先等待millisecondsTimeout秒后,执行WaitAny函数。如果等待millisecondsTimeout期间有调用set方法,则直接返回waitHandles中被释放的线程的index,注意下标从0开始;
如果millisecondsTimeout秒后没有释放线程,目前机器上测试会返回258这个数字
知识点
多线程中使用集合
使用集合时,必须lock住集合,否则会报错的
e.g
lock (((ICollection)list).SyncRoot)
知识点
WaitHandle.SignalAndWait 方法的使用
其中一种定义public static bool SignalAndWait (System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn);
说明:向一个 WaitHandle 发出信号并等待另一个。即对第一个参数调用Set方法,第二个参数调用waitone方法
e.g
public class SignalAndWait_Bll
{
// The EventWaitHandle used to demonstrate the difference
// between AutoReset and ManualReset synchronization events.
//
private static EventWaitHandle ewh;
// A counter to make sure all threads are started and
// blocked before any are released. A Long is used to show
// the use of the 64-bit Interlocked methods.
//
private static long threadCount = 0;
// An AutoReset event that allows the main thread to block
// until an exiting thread has decremented the count.
//
private static EventWaitHandle clearCount =
new EventWaitHandle(false, EventResetMode.AutoReset);
public void Go()
{
// Create an AutoReset EventWaitHandle.
//
ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
// Create and start five numbered threads. Use the
// ParameterizedThreadStart delegate, so the thread
// number can be passed as an argument to the Start
// method.
for (int i = 0; i <= 4; i++)
{
Thread t = new Thread(
new ParameterizedThreadStart(ThreadProc)
);
t.Start(i);
}
// Wait until all the threads have started and blocked.
// When multiple threads use a 64-bit value on a 32-bit
// system, you must access the value through the
// Interlocked class to guarantee thread safety.
//
while (Interlocked.Read(ref threadCount) < 5)
{
Thread.Sleep(500);
}
// Release one thread each time the user presses ENTER,
// until all threads have been released.
//
while (Interlocked.Read(ref threadCount) > 0)
{
Console.WriteLine("Press ENTER to release a waiting thread.");
Console.ReadLine();
// SignalAndWait signals the EventWaitHandle, which
// releases exactly one thread before resetting,
// because it was created with AutoReset mode.
// SignalAndWait then blocks on clearCount, to
// allow the signaled thread to decrement the count
// before looping again.
//
WaitHandle.SignalAndWait(ewh, clearCount);
}
Console.WriteLine();
// Create a ManualReset EventWaitHandle.
//
ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
// Create and start five more numbered threads.
//
for (int i = 0; i <= 4; i++)
{
Thread t = new Thread(
new ParameterizedThreadStart(ThreadProc)
);
t.Start(i);
}
// Wait until all the threads have started and blocked.
//
while (Interlocked.Read(ref threadCount) < 5)
{
Thread.Sleep(500);
}
// Because the EventWaitHandle was created with
// ManualReset mode, signaling it releases all the
// waiting threads.
//
Console.WriteLine("Press ENTER to release the waiting threads.");
Console.ReadLine();
ewh.Set();
}
private void ThreadProc(object data)
{
int index = (int)data;
Console.WriteLine("Thread {0} blocks.", data);
// Increment the count of blocked threads.
Interlocked.Increment(ref threadCount);
// Wait on the EventWaitHandle.
ewh.WaitOne();
Console.WriteLine("Thread {0} exits.", data);
// Decrement the count of blocked threads.
Interlocked.Decrement(ref threadCount);
// After signaling ewh, the main thread blocks on
// clearCount until the signaled thread has
// decremented the count. Signal it now.
//
// clearCount.Set();
}
}
知识点
ThreadPool.QueueUserWorkItem方法的使用
其中之一定义:QueueUserWorkItem(WaitCallback, Object)
说明:该静态方法直接使用线程池中可用的线程,第一个参数为回调函数,是WaitCallbak的实例;第二个参数是要传入的参数
e.g
public class Fibonacci_Bll
{
public void Go()
{
const int FibonacciCalculations = 5;
var doneEvents = new ManualResetEvent[FibonacciCalculations];
var fibArray = new Fibonacci[FibonacciCalculations];
var rand = new Random();
Console.WriteLine($"Launching {FibonacciCalculations} tasks...");
for (int i = 0; i < FibonacciCalculations; i++)
{
doneEvents[i] = new ManualResetEvent(false);
var f = new Fibonacci(rand.Next(20, 40), doneEvents[i]);
fibArray[i] = f;
ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
}
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("All calculations are complete.");
for (int i = 0; i < FibonacciCalculations; i++)
{
Fibonacci f = fibArray[i];
Console.WriteLine($"Fibonacci({f.N}) = {f.FibOfN}");
}
}
}
public class Fibonacci
{
private ManualResetEvent _doneEvent;
public Fibonacci(int n, ManualResetEvent doneEvent)
{
N = n;
_doneEvent = doneEvent;
}
public int N { get; }
public int FibOfN { get; private set; }
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine($"Thread {threadIndex} started...");
FibOfN = Calculate(N);
Console.WriteLine($"Thread {threadIndex} result calculated...");
_doneEvent.Set();
}
public int Calculate(int n)
{
if (n <= 1)
{
return n;
}
return Calculate(n - 1) + Calculate(n - 2);
}
}
知识点
Interlocked类的使用
类说明:为多个线程共享的变量提供原子操作。
其中较为常用的静态方法
public static int Increment(ref int location);
public static int Decrement(ref int location);
public static int Exchange(ref int location1, int value);
public static long Read(ref long location);
e.g
private static int threadCount = 0;
Interlocked.Increment(ref threadCount);
坑
报错:WaitHandles 的数目必须少于或等于 64 个
分析:该问题的发生因为创建了过多的EventWaitHandle或其子类,报错很明显WaitHandles数组的子项最多让创建64个
解决方法:转换下思路,只创建一个EventWaitHandle类,使用一个共享变量,对变量进行原子操作,记录次数
e.g 等待100个线程执行完毕
public class eventWaitHandle_Bll
{
private static long threadCount = 0;
private static long dyCount = 100;
private const int lNum = 100;
EventWaitHandle myH = new EventWaitHandle(false, EventResetMode.ManualReset);
public void Go1()
{
for (int i = 0; i < lNum; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(MyPro1), i);
}
myH.WaitOne();
Console.WriteLine(" result number is :{0}", threadCount);
}
private void MyPro1(object obj)
{
int a = (int)obj;
Console.WriteLine("{0} start", a);
Interlocked.Increment(ref threadCount);
Console.WriteLine("{0} end.", a);
Interlocked.Decrement(ref dyCount);
Thread.Sleep(200);
if (Interlocked.Read(ref dyCount) == 0)
{
myH.Set();
}
}
}
高速
string和字节数组byte[]的转换
string转byte[]:
byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str );
byte[]转string:
string str = System.Text.Encoding.Default.GetString ( byteArray );
string转ASCII byte[]:
byte[] byteArray = System.Text.Encoding.ASCII.GetBytes ( str );
ASCII byte[]转string:
string str = System.Text.Encoding.ASCII.GetString ( byteArray );