C#技巧记录——持续更新
作为一名非主修C#的程序员,在此记录下学习与工作中C#的有用内容,持续更新
对类型进行约束,class指定了类型必须是引用类型,new()指定了类型必须具有一个无参的构造函数,规定T类型必须实现IUser,规定T必须为struct
where T : class, new(), T:IUser, T:Struct
创建别名,实现C的typedef类似的功能
using MyInt=System.Int32;//为Int32定义别名
创建从当日00:00:00开始的时间
DateTime date=DateTime.Now; date=date.Date; //通过返回时间的日期部分来解决时间置为0的问题
创建从当月1日到最后一天的时间
DateTime start = DateTime.Now.AddDays(-(int)DateTime.Now.Day + 1).Date; DateTime end = start.AddMonths(1).AddDays(-1);
获取从当年第一天到最后一天的时间
DateTime start = DateTime.Now.AddDays(-DateTime.Now.DayOfYear+1).Date;
DateTime end = start.AddYears(1);
获取当季度第一天到最后一天
int quarter = 0; switch (DateTime.Now.Month) { case 3: case 4: case 5: quarter = 3;break; case 6: case 7: case 8: quarter = 6; break; case 9: case 10: case 11: quarter = 9; break; case 12: case 1: case 2: quarter = 12; break; } DateTime start = DateTime.Now.AddDays(-DateTime.Now.DayOfYear+1).Date.AddMonths(quarter-1); DateTime end = start.AddMonths(3).AddDays(-1);
定义长字符串包含特殊字符
string longStr = @"\[][;\&";
条件编译
//DEBUG一般为编译器预定义的特殊变量,用于表示是否为调试模式 //也可以自定义,使用#define,并声明在文件开始处,同C/C++ #if DEBUG Console.Write("debug"); #else Console.Write("un debug"); #endif #if aa Console.WriteLine("我是A"); #else Console.WriteLine("我是B"); #endif
ref out
//通过ref传递引用 //使用ref传递的值必须初始化 void show(ref int x) { Console.Write(x) } int i=9; show(ref i); //解决了ref需要初始化的问题,使用out不需要对变量进行初始化 void show(out int x) { Console.Write(x) } int i; show(out i);
命名参数
//可以随意交换实参的顺序,冒号之前指定参数名,冒号之后指定值,与swift一致 public static void show(int x,int y) { Console.Write("{0},{1}",x,y); } show(y:9,x:20);
自动实现属性
public int Age { get;set; }
静态构造函数
//在第一次引用类型的之前调用静态构造函数 class test { static int count; static test() { count = 1; } public test() { } public void show() { Console.Write(count); } }
readonly
class test { readonly int count=0;//只允许在初始化或构造函数中修改值 public test() { count = 1; } public void show() { //count = 3; 错误 Console.Write(count); } public int Age { get;set; } }
匿名类型
//常使用创建类的方式来描述json对象,并需要每次创建新的类, //使用匿名对象便可解决此问题 var a = new { age = 0,name="lilei" }; Console.Write(a.age+" "+a.name);
合并运算符
//当我们在使用可空类型的时候经常需要判断值是否为空 //例如 int ? x; if(x==null) { //... } else { //... } //这个时候我们便可以使用合并运算符来处理 // 当x非空时,a的值为x的值。若x为空,a的值为0; int a=x??0;
多维数组定义
//数组定义本身并不困难,这里仅作为和C不同的风格才记录下来,以提醒自己 int [,] users=new int[2,2];
排序
//数组提供的快速排序算法 //要求数组类型是已实现了IComparable接口的类型 int[] te = { 555,6,2,1,65,99,45,63}; Console.Write("*******************\n"); Array.Sort(te); for (int i = 0; i < te.Length; i++) { Console.Write(te[i] + "\n"); }
字符串分割匹配多个字符
str.Split('a','b','c');
使用\r\n分割字符串
var infoStr = examInfo.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
linq
//linq语法与sql类似,不同之处需要将from提前, //便于类型推测,select语句放到最后 //其中d为查询后的对象 //in后为查询的数据来源 int[] ary = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var resul = from d in ary where d == 1 select d; foreach (var item in resul) { MessageBox.Show(item.ToString()); } //可为查询对象设置类型,from后的int,如下 //如果类型错误会产生运行时异常 int[] ary = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var resul = from int d in ary where d == 1 select d; foreach (var item in resul) { MessageBox.Show(item.ToString()); }
使用共享模式读写文件
//共享模式写文件 using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.SetLength(0); using (StreamWriter writer = new StreamWriter(fs,Encoding.Default)) { string infos = JsonConvert.SerializeObject(info.data); writer.Write(infos); writer.Flush(); writer.Dispose(); } fs.Dispose(); } //共享模式读取文件 using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite,FileShare.ReadWrite)) { fs.SetLength(0); using (StreamReader reader = new StreamReader(fs)) { string lifeStr=reader.ReadToEnd(); } fs.Dispose(); }
static&&const
static 表示静态的 const 表示静态的常量
using static
using static Console; class Pragram { //使用using static已经导入了,这里不用加Console Write("Hello"); }
ILDSAM
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools
//在类似目录下
byte、sbyte
byte:无符号 sbyte:有符号
插值字符串
int a=9; string b=$"a:{a}";//使用变量或表达式值填充
lambda表达式
int getDouble(int x)=>x*x;
可变个数的参数
//使用关键字params public static void G(params int[] d) { foreach (var item in d) { Write(item); } }
构造函数初始化器
class A { A(int i) { B = i; } //自动调用相应的构造函数,在此构造函数体之前执行 A():this(1) { }
静态构造函数
static A() { //在第一次调用之前自动初始化 }
readonly
class A { readonly int a; A() { //只能在构造函数中初始化,否则将为该类型的默认值 a=9; } }
表达式体属性(声明类成员时使用lambda)
class A { int a; int b; int c=>a+b; }
匿名类型
var zhangsan=new { name="zhangsan"; age=20 };
override new
如果你用override,则无论调用的是A类还是B类中的TEST(),系统都会找到它实质类的TEST();
如果是用的New,则可以通过类型转换调用到基类的TEST();
获取[Description("")]
public static class EnumHelper { public static string GetDescription(this Enum enumeration) { Type type = enumeration.GetType(); MemberInfo[] memInfo = type.GetMember(enumeration.ToString()); if (null != memInfo && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (null != attrs && attrs.Length > 0) return ((DescriptionAttribute)attrs[0]).Description; } return enumeration.ToString(); } }
is as
is返回判断结果true false as返回转换后的引用,如果转换失败返回null, 转换失败均不抛出异常
空值运算符
//空指针异常 //string i=null ; //Console.WriteLine(i.ToString()); //输出空白字符 string i = null; Console.WriteLine(i?.ToString()); Console.WriteLine("end");
nameof
//获取方法或类的名称
default获取类型默认值
int i=default(int);
checked unchecked
检测代码块是否计算过程中发生溢出,一般不需要unchecked(默认为不检测)
?空值传播与??空值合并
? //如果引用为空,则直接返回null
?? //如果不为空则返回变量值,否则返回??之后的值
var x = new { a = "a", b = "b" }; //如果x为空,则直接返回null var xx = x?.a ?? "";
action func
void a() { } int b() { return 0; } void test() { Action ax=new Action(a); Func<int> af = new Func<int>(b); }
Lazy<>延迟加载
public class Student { public Student() { this.Name = "DefaultName"; this.Age = 0; Console.WriteLine("Student is init..."); } public string Name { get; set; } public int Age { get; set; } } Lazy<Student> stu = new Lazy<Student>(); if(!stu.IsValueCreated) Console.WriteLine("isn't init!"); Console.WriteLine(stu.Value.Name); stu.Value.Name = "Tom"; stu.Value.Age = 21; Console.WriteLine(stu.Value.Name); Console.Read();
WeakReference弱引用对象
弱引用:在引用对象的同时,允许垃圾回收该对象。
对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,
同时希望GC必要时回收时,可以考虑使用弱引用
获取随机文件名
System.Console.WriteLine(Path.GetRandomFileName());
System.Console.WriteLine(Path.GetTempFileName());
System.Console.WriteLine(Path.GetTempPath());
显示TODO标签
视图->任务列表
类型转换
Convert.ChangeType(value, property.PropertyType);
base64转图片
public static void SaveImage(string logoBase64, string path, string imageName) { string finalPath = Path.Combine(path, imageName); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.WriteAllBytes(finalPath, Convert.FromBase64String(logoBase64));//将base64转成图片 }
使用保留的关键字作为变量名
//在变量名称前添加@
//为跨平台提供了便利 public class Test{ public string @class{get;set;} }
获取枚举所有数据
public static Array GetAll(this Enum e)//,dynamic targetObj) { return Enum.GetValues(e.GetType()); }
获取对象Description
public static string Description(this Object AEnum) { Type type = AEnum.GetType(); MemberInfo[] memInfo = type.GetMember(AEnum.ToString()); if (null != memInfo && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (null != attrs && attrs.Length > 0) return ((DescriptionAttribute)attrs[0]).Description; } return AEnum?.ToString(); }
wpf ShowActivated
该值指示在第一次显示窗口时,窗口是否处于激活状态
wpf获取控件所属的窗口
Button button = sender as Button; Window targetWindow = Window.GetWindow(button);
随机获取数据
public static IQueryable<T> RandTake<T>(this IQueryable<T> query, Expression<Func<T, bool>> predicate, int count) { return query.Where(predicate)?.OrderBy(a => Guid.NewGuid())?.Take(count); }
wpf检测窗口是否已经打开过(使用窗口对象引用在对象重置后不会变成null,无法使用是否未null判断窗口是否打开过)
public static bool ISAlive(this Window window) { return Application.Current.Windows.CastToList<Window>().Contains(window); }
WPF获取主窗口
Application.Current.MainWindow
.netCore发布单个exe
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
.netCore发布指定操作系统、架构,发布到指定路径
dotnet publish D:\WebAPI.sln --os win -a x64 -c Release --property:PublishDir=D:\publish
指定c#语言版本
<PropertyGroup> <LangVersion>preview</LangVersion> </PropertyGroup
值 | 含义 |
---|---|
preview |
编译器接受最新预览版中的所有有效语言语法。 |
latest |
编译器接受最新发布的编译器版本(包括次要版本)中的语法。 |
latestMajor (default ) |
编译器接受最新发布的编译器主要版本中的语法。 |
10.0 |
编译器只接受 C# 10 或更低版本中所含的语法。 |
9.0 |
编译器只接受 C# 9 或更低版本中所含的语法。 |
8.0 |
编译器只接受 C# 8.0 或更低版本中所含的语法。 |
7.3 |
编译器只接受 C# 7.3 或更低版本中所含的语法。 |
7.2 |
编译器只接受 C# 7.2 或更低版本中所含的语法。 |
7.1 |
编译器只接受 C# 7.1 或更低版本中所含的语法。 |
7 |
编译器只接受 C# 7.0 或更低版本中所含的语法。 |
6 |
编译器只接受 C# 6.0 或更低版本中所含的语法。 |
5 |
编译器只接受 C# 5.0 或更低版本中所含的语法。 |
4 |
编译器只接受 C# 4.0 或更低版本中所含的语法。 |
3 |
编译器只接受 C# 3.0 或更低版本中所含的语法。 |
ISO-2 (或 2 ) |
编译器只接受 ISO/IEC 23270:2006 C# (2.0) 中所含的语法。 |
ISO-1 (或 1 ) |
编译器只接受 ISO/IEC 23270:2003 C# (1.0/1.2) 中所含的语法。 |
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/configure-language-version
NameValueCollection
与字典不同,在字典的基础上相同的键多次可以多次添加 ``` NameValueCollection nameValueCollection = new NameValueCollection(); nameValueCollection.Add("s", "a"); nameValueCollection.Add("s", "b"); ``` 遍历可以使用 ``` foreach (var item in nameValueCollection.GetValues(0)) { Console.WriteLine(item); } ```
vs配置命名规范
工具->选项->文本编辑器->C#->代码样式->命名
EF相关
关闭状态追踪,AsNoTracking() 关闭状态同步,context.ChangeTracker.AutoDetectChangesEnabled = false
EF中跟踪的数据都会记录在db.Set<T>().Local 对象中,
如果同一个事务中修改并保存了变更,后续再次变更时不得再次跟踪对象,需要先移除跟踪
例
public T Update(T entity)
{
var localData = db.Set<T>().Local.FirstOrDefault(entity);
if (localData!=null)
{
//var state = db.Entry(localData).State;
//if(state== EntityState.Detached)
//{
db.Entry(localData).State = EntityState.Detached;
//}
}
db.Set<T>().Attach(entity).State = EntityState.Modified;
return entity;
}
配置nuget源
dotnet nuget add source [仓库地址] -n [仓库名称]
按周分组
//周日划到上周数据 data.GroupBy(f => f.Day.AddDays(f.Day.DayOfWeek == DayOfWeek.Sunday?- 7: -(int)f.Day.DayOfWeek));
获取运行路径
Directory.GetCurrentDirectory(); //当前路径
Environment.CurrentDirectory; //当前路径
AppDomain.CurrentDomain.BaseDirectory; //程序文件路径
AppDomain.CurrentDomain.SetupInformation.ApplicationBase; //程序文件路径
AppContext
AppContext.SetSwitch("Switch.AmazingLib.ThrowOnException", true);
可以使用此类型来实现动态切换效果,如配置文件为DEBUG模式则自动添加测试数据等
获取值
public class AmazingLib { private bool shouldThrow; public void PerformAnOperation() { if (!AppContext.TryGetSwitch("Switch.AmazingLib.ThrowOnException", out shouldThrow)) { // This is the case where the switch value was not set by the application. // The library can choose to get the value of shouldThrow by other means. // If no overrides or default values are specified, the value should be 'false'. // A false value implies the latest behavior. } // The library can use the value of shouldThrow to throw exceptions or not. if (shouldThrow) { // old code } else { // new code } } }
migration指定上下文
Update-Database -Context BookStoreDbContext
命令行更新项目中的单个nuget包
nuget.exe update X.csproj -Id PackageA
socket打印
string fileName = "PDF_2224101MV.pdf"; string filePath = Path.Combine(Environment.CurrentDirectory, fileName); byte[] buffer; using (Stream stream = new FileStream(filePath,FileMode.OpenOrCreate)) { buffer = new byte[stream.Length - 1]; stream.Read(buffer, 0, buffer.Length); } Socket clientSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); clientSocket.NoDelay = true; IPAddress ip = IPAddress.Parse("10.159.4.28"); IPEndPoint iPEndPoint = new IPEndPoint(ip, 9100); clientSocket.Connect(iPEndPoint); clientSocket.Send(buffer); clientSocket.Close();
!. 一定不会为空
List x=new(); x!.First();
变量名和关键字冲突
变量名前添加@ public bool @checked { get; set; }
[InstantHandle]
标识lambda是立即执行的,可以用此属性通过lambda来传递运行时参数给后续的回调
Microsoft.Windows.Compatibility
framework迁移到.netcore的过程中缺失了一部分api,这部分缺失的api(如drawing, EventLog, WMI, Performance Counters)在Microsoft.Windows.Compatibility中基本都有补充
指定字符集报错问题
''GB2312' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
//注册字符集
Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var bytes = Encoding.GetEncoding("GB2312").GetBytes(str);
MIME类型预定义字符串 - 系统已经自带,不需要再自定义
联系我:renhanlinbsl@163.com