对象哈希码
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转型 概念:
- 所有表达式都能隐式的转化为dynamic,因为所有表达式都最终生成从Object继承的类型;
- 将代码表达式从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在运行时得到其类型信息,直接使用方法;