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类型预定义字符串 - 系统已经自带,不需要再自定义

 

 

 

 

posted @ 2017-04-22 19:45  Hey,Coder!  阅读(482)  评论(0编辑  收藏  举报