本文来告诉大家在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# 很少人知道的科技的更多相关文章

  1. WPF 很少人知道的科技

    原文:WPF 很少人知道的科技 本文介绍不那么常见的 WPF 相关的知识. 本文内容 在 C# 代码中创建 DataTemplate 多个数据源合并为一个列表显示 使用附加属性做缓存,避免内存泄漏 使 ...

  2. 2019-11-29-C#-很少人知道的科技

    title author date CreateTime categories C# 很少人知道的科技 lindexi 2019-11-29 10:12:43 +0800 2018-03-16 08: ...

  3. XAML 很少人知道的科技 - walterlv

    原文:XAML 很少人知道的科技 - walterlv XAML 很少人知道的科技 发布于 2019-04-30 02:30 更新于 2019-04-30 11:08 本文介绍不那么常见的 XAML ...

  4. 2019-5-27-C#-很少人知道的科技

    title author date CreateTime categories C# 很少人知道的科技 lindexi 2019-05-27 19:33:36 +0800 2018-03-16 08: ...

  5. 11 个很少人知道但很有用的 Linux 命令

    Linux命令行吸引了大多数Linux爱好者.一个正常的Linux用户一般掌握大约50-60个命令来处理每日的任务.Linux命令和它们的转换对于Linux用户.Shell脚本程序员和管理员来说是最有 ...

  6. 很少人知道的office专用卸载工具

    Microsoft Office是微软公司开发的一套基于 Windows 操作系统的办公软件套装.常用组件有 Word.Excel.Powerpoint等.当我们不需要再用了或者想安装旧版本的话,首先 ...

  7. 几个超级实用但很少人知道的 VS 技巧

    大家好,今天分享几个我知道的实用 VS 技巧,而这些技巧我发现很多人都不知道.因为我经常在工作中遇到:我在同事电脑上解决问题,或在会议上演示代码示例时,使用了一些 VS "骚"操作 ...

  8. 几个超级实用但很少人知道的 VS 技巧[更新]

    大家好,今天分享一些实用的 VS 技巧,而这些技巧我发现很多人都不知道.因为我经常在工作中遇到:我在同事电脑上解决问题,或在会议上演示代码示例时,使用了一些 VS "骚"操作,他们 ...

  9. Dubbo 几个很实用但是很少人知道的功能

    dubbo功能非常完善,很多时候我们不需要重复造轮子,下面列举一些你不一定知道,但是很好用的功能; 直连Provider 在开发及测试环境下,可能需要绕过注册中心,只测试指定服务提供者,这时候可能需要 ...

随机推荐

  1. HttpWebRequest 模拟浏览器访问网站

    最近抓网页时报错: 要么返回 The remote server returned an error: (442)要么返回: 非法访问,您的行为已被WAF系统记录! 想了想,就当是人家加了抓网页的东西 ...

  2. Day 13 迭代器,生成器.

    一.迭代器 可以进行for循环的 数据类型 str ,list tuple dict set 文件句柄 什么是可迭代对象? 方法一:dir(被测对象) 如果他含有__iter__,那这个对象就叫做可迭 ...

  3. Xshell连接不上Linux

    用Xshell连接Linux的时候报错了: Connecting to 192.168.79.147:22...Could not connect to '192.168.79.147' (port ...

  4. 大数据技术之_19_Spark学习_01_Spark 基础解析小结(无图片)

    1.准备安装包 2.Spark Standalone 即独立模式  2.1.解压安装包到你安装的目录.  2.2.拷贝 conf 目录下的 slaves 文件,将 slave 节点的 hostname ...

  5. 云链接 接口不允许 情况 解决方法 mysql Host is not allowed to connect to this MySQL server解决方法

    在装有MySQL的机器上登录MySQL mysql -u root -p密码 执行use mysql; 执行update user set host = '%' where user = 'root' ...

  6. Django的常用方法以及配置

    在setting 中配置能生成  sql log 的内容 LOGGING = { , 'disable_existing_loggers': False, 'handlers': { 'console ...

  7. android Service 学习总结

    学习android开发已经四五个月,由于项目中职责的原因一直没有接触过Service的实际项目,今天重新学一遍Service用法. 问题: 作为四大组件,为什么需要Service? 它与Thread又 ...

  8. Linq基础知识小记三

    1.子查询 Linq中的子查询思想和Sql中的子查询其实差不多, 对于方法语法,一个子查询包含在另一个子查询的Lambda表达式中,代码如下: string[] names = { "Jam ...

  9. django第三课 模版

    第一步 创建项目文件: django-admin.py startproject *** 第二步 进入该文件下创建文件夹templates,在该文件夹下创建thanks.html <!DOCTY ...

  10. jQuery表格自动增加

    <!DOCTYPE html> <html dir="ltr" lang="zh-CN"> <head> <meta ...