C# 很少人知道的科技
本文来告诉大家在C#很少有人会发现的科技。即使是工作了好多年的老司机也不一定会知道,如果觉得我在骗你,那么请看看下面
因为C#在微软的帮助,已经从原来很简单的,到现在的很好用。在10多年,很少人知道微软做了哪些,我在网上找了很多大神的博客,然后和很多大神聊天,知道了一些科技,所以就在这里说。如果大家看到这个博客里面没有的科技,请告诉我。
无限级判断空
在 C# 6.0 可以使用??判断空,那么就可以使用下面代码
var v1 = "123";
string v2 = null;
string v3 = null;
var v = v1 ?? v2 ?? v3;
实际上可以无限的使用??
using 省略长的定义
例如有这个代码,使用了很多的 List ,里面有很多定义
var foo =
new System.Collections.Generic.Dictionary<
System.Collections.Generic.List<System.Collections.Generic.List<string>>, string>();
可以看到需要写很多代码,如果这个值作为参数,才是可怕。
一个简单的方法是使用 using HvcnrclHnlfk= System.Collections.Generic.Dictionary<System.Collections.Generic.List<System.Collections.Generic.List<string>>,string>; ,这个文件里的所有定义都可以使用 using 后面的值可以代替。
var foo = new HvcnrclHnlfk();
辣么大
实际上我有些不好意思,好像刚刚说的都是大家都知道的,那么我就要开始写大家很少知道
Func<string,string, EventHandler> foo = (x, y) => (s, e) =>
{
var button = (Button) s;
button.Left = x;
button.Top = y;
};
Button1.Click += foo(0, -1);
看一下就知道这个定义可以做什么
千万不要告诉我,你觉得上面编译不通过,实际上我用了黑科技
但是不告诉你
冲突的类型
如果遇到两个命名空间相同的类型,很多时候都是把命名空间全写
var webControl = new System.Web.UI.WebControls.Control();
var formControl = new System.Windows.Forms.Control();
如果经常使用这两个控件,那么就需要写空间,代码很多,但是微软给了一个坑,使用这个可以不用写空间
using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;
web::Control webControl = new web::Control();
win::Control formControl = new win::Control();
参见:https://stackoverflow.com/a/9099/6116637
extern alias
如果使用了两个 dll ,都有相同命名空间和类型,那么如何使用指定的库
//a.dll
namespace F
{
public class Foo
{
}
}
//b.dll
namespace F
{
public class Foo
{
}
}
这时就可以使用 extern alias
参见:C#用extern alias解决两个assembly中相同的类型全名 - fresky - 博客园
字符串
大家看到了 C# 6.0 的$,是不是可以和@一起?
var str = "kktpqfThiq";
string foo = $@"换行
{str}";
注意两个的顺序,反过来直接告诉你代码不能这样写
表达式树获取函数命名
定义一个类,下面通过表达式树从类获得函数命名
class Foo
{
public void KzcSevfio()
{
}
}
static void Main(string[] args)
{
GetMethodName<Foo>(foo => foo.KzcSevfio());
}
private static void GetMethodName<T>(Expression<Action<T>> action) where T : class
{
if (action.Body is MethodCallExpression expression)
{
Console.WriteLine(expression.Method.Name);
}
}
这样就可以拿到函数的命名
特殊关键字
实际上有下面几个关键字是没有文档,可能只有垃圾微软的编译器才知道
__makeref
__reftype
__refvalue
__arglist
不过在 C# 7.2 都可以使用其他的关键字做到一些,详细请看我的 C# 7.0 博客
DebuggerDisplay
如果想要在调试的时候,鼠标移动到变量显示他的信息,可以重写类的 ToString
public sealed class Foo
{
public int Count { get; set; }
public override string ToString()
{
return Count.ToString();
}
}

但是如果 ToString 被其他地方用了,如何显示?
垃圾微软告诉大家,使用 DebuggerDisplay 特性
[DebuggerDisplay("{DebuggerDisplay}")]
public sealed class Foo
{
public int Count { get; set; }
private string DebuggerDisplay => $"(count {Count})";
}
他可以使用私有的属性、字段,使用方法很简单
参见Using the DebuggerDisplay Attribute
使用 Unions (C++ 一样的)
如果看到 C++ 可以使用内联,不要说 C# 没有,实际上也可以使用 FieldOffset ,请看下面
[StructLayout(LayoutKind.Explicit)]
public class A
{
[FieldOffset(0)]
public byte One;
[FieldOffset(1)]
public byte Two;
[FieldOffset(2)]
public byte Three;
[FieldOffset(3)]
public byte Four;
[FieldOffset(0)]
public int Int32;
}
这时就定义了int变量,修改他就是修改其他的三个
static void Main(string[] args)
{
A a = new A { Int32 = int.MaxValue };
Console.WriteLine(a.Int32);
Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);
a.Four = 0;
a.Three = 0;
Console.WriteLine(a.Int32);
}
这时会输出
2147483647
FF FF FF 7F
65535
接口默认方法
实际上可以给接口使用默认方法,使用的方式
public static void Foo(this IF1 foo)
{
//实际上大家也看到是如何定义
}
数字格式
string format = "000;-#;(0)";
string pos = 1.ToString(format); // 001
string neg = (-1).ToString(format); // -1
string zer = 0.ToString(format); // (0)
参见:自定义数字格式字符串
stackalloc
实际上很多人都不知道这个,这是不安全代码,从栈申请空间
int* block = stackalloc int[100];
参见:stackalloc
调用堆栈
如果需要获得调用方法的堆栈,可以使用这个文章的方法
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
foo.F1();
}
}
public sealed class Foo
{
public void F1()
{
F2();
}
void F2()
{
var stackTrace = new StackTrace();
var n = stackTrace.FrameCount;
for (int i = 0; i < n; i++)
{
Console.WriteLine(stackTrace.GetFrame(i).GetMethod().Name);
}
}
}
输出
F2
F1
参见:WPF 判断调用方法堆栈
指定编译
如果使用 Conditional 可以让代码在指定条件不使用,我写了这个代码,在 Release 下就不会使用 F2
public sealed class Foo
{
public Foo F1()
{
Console.WriteLine("进入F1");
return this;
}
[Conditional("DEBUG")]
public void F2()
{
Console.WriteLine("F2");
}
}
简单让代码跑一下
static void Main(string[] args)
{
var foo = new Foo();
foo.F1();
foo.F2();
}
结果是什么,大家也知道,在 Debug 和 Release 输出是不相同。但是这么简单的怎么会在这里说,请大家看看这个代码输出什么
static void Main(string[] args)
{
var foo = new Foo();
foo.F1().F2();
}
实际上在 Release 下什么都不会输出,F1 不会被执行
true 判断
下面写个见鬼的代码
var foo = new Foo(10);
if (foo)
{
Console.WriteLine("我的类没有继承 bool ,居然可以这样写");
}
没错 Foo 没有继承 bool 居然可以这样写
实际上就是重写 true ,请看代码
public class Foo
{
public Foo(int value)
{
_count = value;
}
private readonly int _count;
public static bool operator true(Foo mt)
{
return mt._count > 0;
}
public static bool operator false(Foo mt)
{
return mt._count < 0;
}
}
是不是觉得很多有人这样写,下面让大家看一个很少人会知道的科技,感谢walterlv
await 任何类型
await "林德熙逗比";
await "不告诉你";
这个代码是可以编译通过的,但是只有在我的设备,然后看了这个博客,可能你也可以在你的设备编译
变量名使用中文
实际上在C#支持所有 Unicode ,所以变量名使用中文也是可以的,而且可以使用特殊的字符
public string H\u00e5rføner()
{
return "可以编译";
}


if this == null
一般看到下面的代码都觉得是不可能
if (this == null) Console.WriteLine("this is null");
如果在 if 里面都能使用 this == null 成立,那么一定是vs炸了。实际上这个代码还是可以运行。
在一般的函数,如 Foo ,在调用就需要使用f.Foo()的方法,方法里 this 就是 f ,如果 f == null 那么在调用方法就直接不让运行,如何到方法里的判断
f.Foo(); //如果 f 为空,那么这里就不执行
void Foo()
{
// 如果 this 为空,怎么可以调用这个方法
if (this == null) Console.WriteLine("this is null");
}
实际上是可以做的,请看(C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切 - walterlv
如上面博客,关键在修改callvirt 为 call,直接修改 IL 可以做出很多特殊的写法。
那么这个可以用在哪里?可以用在防止大神反编译,如需要使用下面逻辑
//执行的代码
//不执行的代码
if(true)
{
//执行的代码
}
else
{
//不执行的代码
}
但是直接写 true 很容易让反编译看到不使用代码,而且在优化代码会被去掉,所以可以使用下面代码
if(this == null)
{
//执行的代码
}
else
{
//不执行的代码
}

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 很少人知道的科技的更多相关文章
- WPF 很少人知道的科技
原文:WPF 很少人知道的科技 本文介绍不那么常见的 WPF 相关的知识. 本文内容 在 C# 代码中创建 DataTemplate 多个数据源合并为一个列表显示 使用附加属性做缓存,避免内存泄漏 使 ...
- 2019-11-29-C#-很少人知道的科技
title author date CreateTime categories C# 很少人知道的科技 lindexi 2019-11-29 10:12:43 +0800 2018-03-16 08: ...
- XAML 很少人知道的科技 - walterlv
原文:XAML 很少人知道的科技 - walterlv XAML 很少人知道的科技 发布于 2019-04-30 02:30 更新于 2019-04-30 11:08 本文介绍不那么常见的 XAML ...
- 2019-5-27-C#-很少人知道的科技
title author date CreateTime categories C# 很少人知道的科技 lindexi 2019-05-27 19:33:36 +0800 2018-03-16 08: ...
- 11 个很少人知道但很有用的 Linux 命令
Linux命令行吸引了大多数Linux爱好者.一个正常的Linux用户一般掌握大约50-60个命令来处理每日的任务.Linux命令和它们的转换对于Linux用户.Shell脚本程序员和管理员来说是最有 ...
- 很少人知道的office专用卸载工具
Microsoft Office是微软公司开发的一套基于 Windows 操作系统的办公软件套装.常用组件有 Word.Excel.Powerpoint等.当我们不需要再用了或者想安装旧版本的话,首先 ...
- 几个超级实用但很少人知道的 VS 技巧
大家好,今天分享几个我知道的实用 VS 技巧,而这些技巧我发现很多人都不知道.因为我经常在工作中遇到:我在同事电脑上解决问题,或在会议上演示代码示例时,使用了一些 VS "骚"操作 ...
- 几个超级实用但很少人知道的 VS 技巧[更新]
大家好,今天分享一些实用的 VS 技巧,而这些技巧我发现很多人都不知道.因为我经常在工作中遇到:我在同事电脑上解决问题,或在会议上演示代码示例时,使用了一些 VS "骚"操作,他们 ...
- Dubbo 几个很实用但是很少人知道的功能
dubbo功能非常完善,很多时候我们不需要重复造轮子,下面列举一些你不一定知道,但是很好用的功能; 直连Provider 在开发及测试环境下,可能需要绕过注册中心,只测试指定服务提供者,这时候可能需要 ...
随机推荐
- vux 入门备忘大佬多指点
一.安装node.js https://nodejs.org/en/ 这样就可以使用npm喽 二.安装vux 安装vux npm install vux --save 安装vux-loader npm ...
- vs2017 修改项目名称
由于经常接到各种项目需求, 又不想重新搭建框架. 于是便想到直接修改项目名. 话不多说, 上图~ 1 重命名 解决方案 和 项目名称 2 重命名项目的应用程序名和命名空间 3 Ctrl+F 将旧的工 ...
- sql添加字段说明
1,sql字段说明 添加 exec sp_addextendedproperty N'MS_Description', N'主键', N'user', N'dbo', N'table', N'Fre ...
- winform程序更新
更新程序和主程序是分开的,得在做一个exe可执行更新程序. 主程序在登陆时判断是否需要更新. 我这边判断方式是直接在配置文件里面设置版本号,然后和服务器上面的版本对比,低于服务器版本就更新程序. // ...
- 批处理系列(18) - 基于BitLocker的开锁上锁
首先要配置好BitLocker. 上锁 lock.bat @echo off rem 上锁前要结束一些程序,浏览器要注意:有恢复上次关闭项功能,按需设置取消该操作 taskkill /f /t /im ...
- 2019年新出现的ocp 062考试原题-2
2.Which three statements are true about pfiles, spfiles or both? A) All spfile parameters can be mod ...
- bonjour browser 下载
在Mac 上叫 Bonjour Browser http://www.macupdate.com/app/mac/13388/bonjour-browser/download IOS 上的 app 叫 ...
- 怎样使用Navicat Premium导出导入mysql数据库
首先,在Navicat Premium中连接要导出数据库的mysql数据库. 2 1.填写好连接数据库的信息后就可以连接到需要导出的数据库了. 3 打开要导出的数据库. 4 将数据库的结构和数据导出为 ...
- day 52 Django 的中间件加载顺序
前情提要: django的中间键的作用是进行加载 可以通过中间键进行辅助操作 1.中间件的概念 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局 ...
- HBase 安装设置
一.安装环境 1. JDK:jdk-7u79-linux-x64.tar.gz 2. HBase:hbase-0.98.13-hadoop1-bin.tar.gz 3. Hadoop:hadoop-1 ...