C#系列之:快速了解基元类型与对象哈希码

对象哈希码

GetHashCode虚方法 System.Object提供了GetHashCode虚方法,可以获得任意对象的Int32哈希码;

GetHashCode与自定义类型的重写

  • 内容
    • 此GetHashCode虚方法可以在子类中被进行重写,并且如果自定义类型重写了Equals,则此GetHashCode建议一定要重写。
  • 原因
    • 因为在一些数据结构,比如字典或者哈希表当中,其内部算法实现时是基于对象类型的Equals来检测两个对象是否相等,而如果重写了Equals,则还需要其对应的GetHashCode方法来确保两个对象不仅在每个字段上相等,还确保其在哈希码上也相等。
    • 基于引用类型的变量需要

自定义GetHashCode 参考实现:

C# 复制代码
internal sealed class Point
{
	private readonly Int32 m_x,m_y;
	public override Int32 GetHashCode()
	{
		return m_x ^ m_y;
	}
}

自定义计算哈希码注意规则

  • 1、算法提供良好的随机分布
  • 2、可在算法中调用基类的GetHaseCode,但是不要调用Object或者ValueType当中的GetHashCode方法,因为这两者由于内容过于抽象,实现结果和高性能哈希算法不沾边;
  • 3、算法至少使用一个实例字段,并且此实例字段应该为不可变;
  • 4、包含相同值的不同对象应该返回相同的哈希码;

dynamic基元类型

类型安全的含义 含义:

  • C#是类型安全的语言,这意味着所有代码中出现的表达式,都会被解析成类型的实例,编译器生成的代码只执行对该类型有效的操作。 类型安全的优势:
  • 程序员犯得许多错误都可以在编译时检测到,确保代码在尝试执行前是正确的;
  • 因为会在编译时做出更多的预设,可以编译出更小、更快的代码; 不足:
  • 程序有时仍然需要处理一些运行时才会知晓的信息,尤其是在和一些不使用C#实现的组件之间进行通信时,有时经常会需要开发人员和其他组件进行通信;

dynamic关键字 出现原因:

  • 为了方便开发人员使用反射或者和其他组件之间进行通信,C#编译器允许将表达式的类型或者结果变量标记为dynamic,进而用dynamic来调用成员。 Payload:
  • 代码使用dynamic时,编译器会生成特殊的IL代码来描述所需操作,这些特殊的代码被称为payload,在运行时payload代码根据dynamic表达式或者变量引用的对象的实际类型来决定具体执行的操作;

dynamic执行时行为

代码演示

C# 复制代码
internal class Program
	{
		static void Main(string[] args)
		{
			dynamic value;
			for (int i = 0; i < 2; i++)  
			{
				value = (i == 0) ? (dynamic)5 : (dynamic)"A";
				value = value + value;
				M(value);
			}
		}

		private static void M(Int32 n) 
		{
			Console.WriteLine("M(Int32)" + n.ToString());
		}
		private static void M(string s)
		{
			Console.WriteLine("M(String)" + s);
		}
	}

概念:

  • 核心:编译器会将dynamic转化成Object,并且添加DynamicAttribute实例;
  • 当两个操作数的类型时dynamic时,C#编译器会生成payload代码在运行时检查value的实际类型;
  • 如果字段、方法参数或者方法返回值的类型是dynamic,编译器会将该类型转换为System.Object,并在元数据中向字段、参数、返回值类型变量应用System.Runtime.CompilerSerivces.DynamicAttribute的实例,局部变量不会应用此,但也会成为Object;

dynamic类型转换

dynamic转型 概念:

  1. 所有表达式都能隐式的转化为dynamic,因为所有表达式都最终生成从Object继承的类型;
  2. 将代码表达式从Object转型成其他类型需要显示转型,但编译器允许使用隐式转型将dynamic转型为其他类型。如果对象类型不兼容,CLR会抛出InvalidCastException异常; 演示:
C# 复制代码
dynamic n1 = 32;//OK
Int32 n2 = n1;//OK

dynamic与var var:

  • var要求编译器根据表达式推断具体数据类型,只能在方法内部声明局部变量; dynamic:
  • dynamic可以使用在局部变量、字段以及参数当中;
  • 表达式不能转型为var,但能转型为dynamic;

dynamic与反射 使用分析:

  • 优点:
    • 使用C#的dynamic可以显著简化语法;
  • 缺点:
    • payload代码执行时,会在程序运行时生成动态代码,这些代码进入住留存于内存的程序集,加载这些程序集会产生额外的内存消耗。
  • 使用:
    • 如果程序只是一、两个地方需要动态行为,使用传统的反射方法更加高效;

演示:

C# 复制代码
dynamic target = "Mike";
dynamic arg = "ff";
Boolean result = target.Contains(arg);

Contains是String类当中的方法,通过dynamic在运行时得到其类型信息,直接使用方法;

相关推荐
TIF星空4 小时前
【使用 C# 获取 USB 设备信息及进行通信】
开发语言·经验分享·笔记·学习·microsoft·c#
csdn_aspnet6 小时前
如何在 C# 中自定义 Datagridview 标题
c#·winform·datagridview
津津有味道6 小时前
MIFARE DESFire Light 卡C#读写更改卡片密钥源码
c#·light·desfire·ev2
炯哈哈9 小时前
【上位机——WPF】Window标签常用属性
开发语言·c#·wpf·上位机
江沉晚呤时15 小时前
C# 实现雪花算法(Snowflake Algorithm)详解与应用
c#·.net
酷炫码神17 小时前
C#语法基础
开发语言·c#
酷炫码神19 小时前
C#数据类型
java·服务器·c#
CodeCraft Studio20 小时前
国产化Word处理控件Spire.Doc教程:通过C# 删除 Word 文档中的超链接
开发语言·c#·word
ghost1431 天前
C#学习第22天:网络编程
开发语言·学习·c#
神仙别闹1 天前
基于C#实现中央定位服务器的 P2P 网络聊天系统
服务器·网络·c#