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

相关推荐
向宇it10 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
向宇it11 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
坐井观老天16 小时前
在C#中使用资源保存图像和文本和其他数据并在运行时加载
开发语言·c#
pchmi18 小时前
C# OpenCV机器视觉:模板匹配
opencv·c#·机器视觉
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭20 小时前
C#都可以找哪些工作?
开发语言·c#
boligongzhu1 天前
Dalsa线阵CCD相机使用开发手册
c#
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇23】C#面向对象继承——`as`类型转化和`is`类型检查、向上转型和向下转型、里氏替换原则(LSP)
java·开发语言·unity·c#·游戏引擎·里氏替换原则
sukalot1 天前
windows C#-命名实参和可选实参(下)
windows·c#
小码编匠1 天前
.NET 下 RabbitMQ 队列、死信队列、延时队列及小应用
后端·c#·.net