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在运行时得到其类型信息,直接使用方法;

相关推荐
运维开发小白4 小时前
使用夜莺 + Elasticsearch进行日志收集和处理
运维·c#·linq
幻想趾于现实5 小时前
C# Winform 入门(4)之动图显示
开发语言·c#·winform
向宇it7 小时前
【零基础入门unity游戏开发——2D篇】SortingGroup(排序分组)组件
开发语言·unity·c#·游戏引擎·材质
军训猫猫头8 小时前
87.在线程中优雅处理TryCatch返回 C#例子 WPF例子
开发语言·ui·c#·wpf
du fei8 小时前
C# 与 相机连接
开发语言·数码相机·c#
古力德9 小时前
Unity中造轮子:定时器
c#·unity3d
小码编匠10 小时前
C# 实现西门子S7系列 PLC 数据管理工具
后端·c#·.net
“抚琴”的人1 天前
【机械视觉】C#+VisionPro联合编程———【六、visionPro连接工业相机设备】
c#·工业相机·visionpro·机械视觉
FAREWELL000751 天前
C#核心学习(七)面向对象--封装(6)C#中的拓展方法与运算符重载: 让代码更“聪明”的魔法
学习·c#·面向对象·运算符重载·oop·拓展方法
CodeCraft Studio1 天前
Excel处理控件Spire.XLS系列教程:C# 合并、或取消合并 Excel 单元格
前端·c#·excel