July 1, 2023
By: Kevin
C#中的一些小技巧
- 字符串和二进制写入文件
- 反编译dll的工具, 用来查看dll中的信息,包括namespace, class, functions.
- 动态载入dll的类
- 获取UniqID
- 获取环境信息
- Task的异常处理
- 模式匹配
- 退出应用程序
- 获取当前目录
- 获取临时文件&目录
- 字符串或者字符串数组写入文件
- 获取类型名称
- Dictionary
字符串和二进制写入文件
System.IO.File.WriteAllBytes(@"object.bin", bs);
System.IO.File.WriteAllText(@"s0file.txt", s0);
反编译dll的工具, 用来查看dll中的信息,包括namespace, class, functions.
- ilspy, macos/windows都可以用, mac下安装
brew install --cask ilspy
动态载入dll的类
如果是程序已经载入的dll, 可以用Type taskType = Type.GetType($"MyClass"); 来载入其中的类 对于需要动态载入的, 需要:
string relativePath = "./ExampleSubTasks.dll";
string absolutePath = Path.GetFullPath(relativePath);
Assembly assembly = Assembly.LoadFile(absolutePath);
Type taskType = assembly.GetType(typeName);
获取UniqID
Console.WriteLine(Guid.NewGuid().ToString().Replace("-", ""));
获取环境信息
using System.Runtime.InteropServices;
// 获取当前操作系统的版本信息
OperatingSystem os = Environment.OSVersion;
Version version = os.Version;
// 使用 RuntimeInformation 获取操作系统信息
string osDescription = RuntimeInformation.OSDescription;
Architecture osArch = RuntimeInformation.OSArchitecture;
Console.WriteLine("操作系统版本: " + version);
Console.WriteLine("操作系统描述: " + osDescription);
Console.WriteLine("操作系统架构: " + osArch);
Task的异常处理
Task中异步执行的异常悄无声息
AppDomain.CurrentDomain.UnhandledException += (o, e ) =>
Console.WriteLine($"Unhandled exception occurs {e.ExceptionObject}.");
_ = Task.Run(() => throw new Exception("DoWork failed."));
await Task.Delay(100);
Console.WriteLine("没有错误");
只有阻塞式的才会有异常抛出.
AppDomain.CurrentDomain.UnhandledException += (o, e ) =>
Console.WriteLine($"Unhandled exception occurs {e.ExceptionObject}.");
await Task.Run(() => throw new Exception("DoWork failed."));
await Task.Delay(100);
但是, 很多时候我们就是不想阻塞呀…可以每次都try, catch, 可以解决问题, 就是有点麻烦
try {
await Task.Run(() => {
throw new Exception("DoWork failed.");
});
}
catch (Exception e) {Console.WriteLine(e.StackTrace);}
await Task.Delay(100);
我们有个更好的方式
public static class TaskExtensions
{
public static Task FailFastOnException(this Task task)
{
task.ContinueWith(c => Environment.FailFast("Task faulted", c.Exception),
TaskContinuationOptions.OnlyOnFaulted); // 例外發生時才執行。
return task;
}
public static Task IgnoreExceptions(this Task task)
{
task.ContinueWith(c => Console.WriteLine(c.Exception),
TaskContinuationOptions.OnlyOnFaulted); // 例外發生時才執行。
return task;
}
}
Task.Run(() => throw new Exception("DoWork failed.")).FailFastOnException();
is 表达式
检查表达式的类型
int i = 34; object iBoxed = i; int? jNullable = 42; if (iBoxed is int a && jNullable is int b) { Console.WriteLine(a + b); // output 76 }检查是否为null
string input = null; if (input is null) { Console.WriteLine("null"); }使用 否定模式 检查null
string result = "a"; if (result is not null) { Console.WriteLine(result.ToString()); }
模式匹配
NULL检查
int? maybe = 12;
if (maybe is int number)
{
Console.WriteLine($"The nullable int 'maybe' has the value {number}");
}
else
{
Console.WriteLine("The nullable int 'maybe' doesn't hold a value");
}
NOT 表达式
#nullable enable
string? message = "This is not the null string";
if (message is not null)
{
Console.WriteLine(message);
}
针对枚举类型
public enum Operation
{SystemTest, Start, Stop, Reset };
public string PerformOperation(Operation command) =>
command switch
{
Operation.SystemTest => "",
Operation.Start => "",
Operation.Stop => "",
Operation.Reset => "",
_ => throw new ArgumentException("Invalid enum value for command", nameof(command)),
};
#+results:
针对字符串类型
public int PerformOperation(string command) =>
command switch
{
"SystemTest" => 1,
"Start" => 2,
"Stop" => 3,
"Reset" => 4,
_ => throw new ArgumentException("Invalid string value for command", nameof(command)),
};
#+results:
关系模型
string WaterState(int tempInFahrenheit) =>
tempInFahrenheit switch
{
(> 32) and (< 212) => "liquid",
< 32 => "solid",
> 212 => "gas",
32 => "solid/liquid transition",
212 => "liquid / gas transition",
};
#+results:
多个输入
public record Order(int Items, decimal Cost);
public decimal CalculateDiscount(Order order) =>
order switch
{
{ Items: > 10, Cost: > 1000.00m } => 0.10m,
{ Items: > 5, Cost: > 500.00m } => 0.05m,
{ Cost: > 250.00m } => 0.02m,
null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"),
var someObject => 0m,
};
public decimal CalculateDiscount(Order order) =>
order switch
{
( > 10, > 1000.00m) => 0.10m,
( > 5, > 50.00m) => 0.05m,
{ Cost: > 250.00m } => 0.02m,
null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"),
var someObject => 0m,
};
列表模式 (c# 11才支持)
decimal balance = 0m;
foreach (string[] transaction in ReadRecords())
{
balance += transaction switch
{
[_, "DEPOSIT", _, var amount] => decimal.Parse(amount),
[_, "WITHDRAWAL", .., var amount] => -decimal.Parse(amount),
[_, "INTEREST", var amount] => decimal.Parse(amount),
[_, "FEE", var fee] => -decimal.Parse(fee),
_ => throw new InvalidOperationException($"Record {string.Join(", ", transaction)} is not in the expected format!"),
};
Console.WriteLine($"Record: {string.Join(", ", transaction)}, New balance: {balance:C}");
}
#+results:
TODO 模式匹配中的运算符 [模式匹配中的运算符]
退出应用程序
System.Envrionment.Exit(0);
获取当前目录
对于脚本执行, 就是当前脚本所在目录
对于编译执行的目录, 一般是bin的debug目录 bin\Debug\net6.0\
获取临时文件&目录
using System.IO;
Console.WriteLine(Path.GetTempFileName());
Console.WriteLine(Path.GetTempPath());
字符串或者字符串数组写入文件
string text =
"A class is the most powerful data type in C#. Like a structure, " +
"a class defines the data and behavior of the data type. ";
await File.WriteAllTextAsync("WriteText.txt", text);
string[] lines = { "First line", "Second line", "Third line" };
using StreamWriter file = new("WriteLines2.txt");
foreach (string line in lines)
{
if (!line.Contains("Second"))
{
await file.WriteLineAsync(line);
}
}
#+results:
获取类型名称
public static string CSharpName(this Type type)
{
var sb = new StringBuilder();
var name = type.Name;
if (!type.IsGenericType) return name;
sb.Append(name.Substring(0, name.IndexOf('`')));
sb.Append("<");
sb.Append(string.Join(", ", type.GetGenericArguments()
.Select(t => t.CSharpName())));
sb.Append(">");
return sb.ToString();
}
Console.WriteLine(CSharpName(typeof(class("s")));
Dictionary
using System;
using System.Linq;
using System.Collections.Generic;
var cities = new Dictionary<string, string>(){
{"UK", "London, Manchester, Birmingham"},
{"USA", "Chicago, New York, Washington"},
{"India", "Mumbai, New Delhi, Pune"}
};
Console.WriteLine(cities["UK"]); //prints value of UK key
Console.WriteLine(cities["USA"]);//prints value of USA key
//Console.WriteLine(cities["France"]); // run-time exception: Key does not exist
//use ContainsKey() to check for an unknown key
if(cities.ContainsKey("France")){
Console.WriteLine(cities["France"]);
}
//use TryGetValue() to get a value of unknown key
string result;
if(cities.TryGetValue("France", out result))
{
Console.WriteLine(result);
}
Console.WriteLine("---access elements using for loop---");
//use ElementAt() to retrieve key-value pair using index
for (int i = 0; i < cities.Count; i++)
{
Console.WriteLine("Key: {0}, Value: {1}",
cities.ElementAt(i).Key,
cities.ElementAt(i).Value);
}