C# 是缓存type.isSubclassOf(type otherType)还是我必须自己缓存?

C# 是缓存type.isSubclassOf(type otherType)还是我必须自己缓存?,c#,dictionary,caching,type-conversion,subclass,C#,Dictionary,Caching,Type Conversion,Subclass,简单问题: type.isSubclassOfType是否缓存为其他类型的字典 如果不是,这样的电话有多贵 我经常检查这一点,以保持代码的可扩展性,并将我使用最多的方法转换为字典…虽然这并不理想,但取决于实现细节,我们可以看看使用dnSpy的ISSUBClass代码 因此,简单的回答是,在这个版本的Framework4.6中,调用没有被缓存,这意味着向继承层次结构上走 电话费有多高的问题取决于您的用例。您应该衡量代码是否在该方法中花费了大量时间,以及缓存是否有帮助 演出 缓存结果是否值得的问题是

简单问题:

type.isSubclassOfType是否缓存为其他类型的字典

如果不是,这样的电话有多贵


我经常检查这一点,以保持代码的可扩展性,并将我使用最多的方法转换为字典…

虽然这并不理想,但取决于实现细节,我们可以看看使用dnSpy的ISSUBClass代码

因此,简单的回答是,在这个版本的Framework4.6中,调用没有被缓存,这意味着向继承层次结构上走

电话费有多高的问题取决于您的用例。您应该衡量代码是否在该方法中花费了大量时间,以及缓存是否有帮助

演出

缓存结果是否值得的问题是,如何衡量调用与缓存查找所花费的时间。我测试了5个场景:

直接调用 缓存使用:字典 缓存使用:Dictionaryvalue元组 缓存使用:ConcurrentDictionary 缓存使用:ConcurrentDictionary值元组 结果

直接调用-0.15s/调用 缓存使用:字典-0.12s/调用 缓存使用:字典-0.06s/调用 缓存使用:ConcurrentDictionary-0.13s/call 缓存使用:ConcurrentDictionary值元组-0.7s/call 带有值元组的ConcurrentDictionary提供了最佳的线程安全性能,如果您不打算使用来自多个线程的代码,那么带有值元组的简单字典也可以很好地工作

通常,缓存只将调用时间减半,并且没有对缓存中的大量数据执行测试,因此性能可能会随着类的增加而降低。我认为不值得缓存结果

代码


虽然依赖于实现细节并不理想,但我们可以看看使用dnSpy的IsSubclassOf代码

因此,简单的回答是,在这个版本的Framework4.6中,调用没有被缓存,这意味着向继承层次结构上走

电话费有多高的问题取决于您的用例。您应该衡量代码是否在该方法中花费了大量时间,以及缓存是否有帮助

演出

缓存结果是否值得的问题是,如何衡量调用与缓存查找所花费的时间。我测试了5个场景:

直接调用 缓存使用:字典 缓存使用:Dictionaryvalue元组 缓存使用:ConcurrentDictionary 缓存使用:ConcurrentDictionary值元组 结果

直接调用-0.15s/调用 缓存使用:字典-0.12s/调用 缓存使用:字典-0.06s/调用 缓存使用:ConcurrentDictionary-0.13s/call 缓存使用:ConcurrentDictionary值元组-0.7s/call 带有值元组的ConcurrentDictionary提供了最佳的线程安全性能,如果您不打算使用来自多个线程的代码,那么带有值元组的简单字典也可以很好地工作

通常,缓存只将调用时间减半,并且没有对缓存中的大量数据执行测试,因此性能可能会随着类的增加而降低。我认为不值得缓存结果

代码


它不会自动缓存。您必须权衡调用的费用与缓存所需的内存。如果有很多这样的检查,我希望字典中的缓存将提高性能。

它不会自动被缓存。您必须权衡调用的费用与缓存所需的内存。如果有很多这样的检查,我希望字典中的缓存可以提高性能。

似乎所有其他答案都有点过于短视了。类型实际上是由运行时缓存的,但在Type.BaseType级别没有

在这样的情况下,实际上很容易确定是否存在缓存

考虑以下代码,并在实际运行之前尝试猜测输出将是什么:

public static void ToCacheOrNotToCache()
{
    var typeofA = typeof(A);
    var typeofB = typeof(B);
    var getTypeA = new A().GetType();
    var getTypeA2 = new A().GetType();
    var getTypeB = new B().GetType();
    var baseTypeB = getTypeB.BaseType;

    Console.WriteLine(
        $"typeof A ref equals getTypeA: {ReferenceEquals(typeofA, getTypeA)}");
    Console.WriteLine(
        $"typeof B ref equals getTypeB: {ReferenceEquals(typeofB, getTypeB)}");
    Console.WriteLine(
        $"typeof A ref equals baseTypeB: {ReferenceEquals(typeofA, baseTypeB)}");
    Console.WriteLine(
        $"getTypeA ref equals getTypeA2: {ReferenceEquals(getTypeA, getTypeA2)}");
}

class A { }
class B: A { }
当然,仔细检查Type.BaseType的实现应该会提供足够的线索来假设某些缓存正在某个级别上进行==类型,类型是赠送;类型没有值语义,因此如果使用引用相等,则必须意味着每个类型使用一个类型实例

代码的输出当然是:

typeof A ref equals getTypeA: True
typeof B ref equals getTypeB: True
typeof A ref equals baseTypeB: True
getTypeA ref equals getTypeA2: True

看来所有其他的答案都有点太近视了。类型实际上是由运行时缓存的,但在Type.BaseType级别没有

在这样的情况下,实际上很容易确定是否存在缓存

考虑以下代码,并在实际运行之前尝试猜测输出将是什么:

public static void ToCacheOrNotToCache()
{
    var typeofA = typeof(A);
    var typeofB = typeof(B);
    var getTypeA = new A().GetType();
    var getTypeA2 = new A().GetType();
    var getTypeB = new B().GetType();
    var baseTypeB = getTypeB.BaseType;

    Console.WriteLine(
        $"typeof A ref equals getTypeA: {ReferenceEquals(typeofA, getTypeA)}");
    Console.WriteLine(
        $"typeof B ref equals getTypeB: {ReferenceEquals(typeofB, getTypeB)}");
    Console.WriteLine(
        $"typeof A ref equals baseTypeB: {ReferenceEquals(typeofA, baseTypeB)}");
    Console.WriteLine(
        $"getTypeA ref equals getTypeA2: {ReferenceEquals(getTypeA, getTypeA2)}");
}

class A { }
class B: A { }
当然,仔细检查Type.BaseType的实现应该会提供足够的线索来假设某些缓存正在某个级别上进行==类型,类型是赠送;类型没有值语义 因此,如果使用引用相等,则必须意味着每个类型使用一个类型实例

代码的输出当然是:

typeof A ref equals getTypeA: True
typeof B ref equals getTypeB: True
typeof A ref equals baseTypeB: True
getTypeA ref equals getTypeA2: True

但问题仍然存在。。。它有多贵?==或基类型是否昂贵?您发布的代码可能非常便宜,或者正好相反。@中间:因为==只使用Object.ReferenceEquals检查非常便宜:代码:公共静态布尔运算符==RuntimeType left,RuntimeType right{return Object.ReferenceEqualsleft,right;}@TimSchmelter我认为应该是reference equals,但是显然==对于类型是重载的,并且是外部实现的。。所以它不是直接向上的对象。referenceequals公共静态外部布尔运算符==类型left,类型right@TitianCernicova Dragomir:它在某种程度上使用了ReferenceEquals重载,请参见我的最后一条评论是否!=但是问题仍然存在。。。它有多贵?==或基类型是否昂贵?您发布的代码可能非常便宜,或者正好相反。@中间:因为==只使用Object.ReferenceEquals检查非常便宜:代码:公共静态布尔运算符==RuntimeType left,RuntimeType right{return Object.ReferenceEqualsleft,right;}@TimSchmelter我认为应该是reference equals,但是显然==对于类型是重载的,并且是外部实现的。。所以它不是直接向上的对象。referenceequals公共静态外部布尔运算符==类型left,类型right@TitianCernicova Dragomir:它在某种程度上使用了ReferenceEquals重载,请参见我的最后一条评论是否!=天气