【问题标题】:Comparing typeof(Type) to System.RuntimeType将 typeof(Type) 与 System.RuntimeType 进行比较
【发布时间】:2017-12-18 03:21:39
【问题描述】:

首先,我确实有解决这个问题的方法(使用 type.FullName),所以它只是为了兴趣。

*为澄清而编辑;这实际上只是一个比较代码中类型类型的最佳方法的问题。

object o;
Type t = typeof(someclass);
o = t;

// Cant do this
if (o.GetType() == typeof(RuntimeType)) {
}

附加到 o 的对象可以是任何东西,包括类型。我正在检查对象的类型以了解如何进一步处理它。因此,如果它是一个字符串,我可能会做一件事,如果它是一个枚举,我可能会做其他事情,如果它是一个类型,我可能会再次做其他事情。我基本上处理的是与 String.Format("",x,y,z) 相同的东西,其中参数都是完全任意的。

我会写

if (o.GetType().FullName == "System.RuntimeType") {} or
if (o.GetType()== typeof(Type).GetType()) {}

但两者都非常难看(虽然它有效)。

原问题:

抱歉,如果之前有人问过这个问题,但我找不到完全匹配的问题(有很多如何获取对象类型、对象是类或 object.GetType() 样式的问题。)

这个问题很接近,但它并不完全相同,因为我无法避免在类型上调用 GetType(我不认为?希望我没有忽略一些非常简单或欺骗性的东西......); What's the difference between System.Type and System.RuntimeType in C#?

所以基本上,我创建了一个带有任意数量参数的属性。这些可以是任何对象,包括类型(我使用类型来决定应该如何处理属性附加到的属性)。例如,虽然属性可以是整数,但该整数是数据库中某个特定表的主键。如果我将这种类型分配给属性,我可以编写通用代码来处理任何类型的对象,而无需编写大量特殊情况代码。也就是说,我可以使用字符串或任何其他值,例如枚举,但是由于模型已经存在,因此似乎没有任何意义不使用它们,因为我可以使用 Activator.CreateContext() 基于创建它们的实例传入的类型。

[AttributeUsage(AttributeTargets.Property)]
public class SomeAttribute: System.Attribute
{
    public SomeAttribute(params object[] parameters)
    {
        foreach(var p in parameters) {
            ...
            // Type of Type.  Uh oh.
            Type t = p.GetType();

            // Evaluates as false when t is of type Type(its actually RuntimeType, with is protected). Sad face.
            if (t == typeof(Type)) {
                ...
            }
            ...
        }
    }
}

我已经在一些属性上添加了这个属性;

public class someclass
{
    [SomeAttribute(..., typeof(someotherclass))
    public sometype someproperty { get; set; }
}

当程序到达时

if (t == typeof(Type))

如果总是返回 false。 t 的类型被评估为 System.RuntimeType 而不是 System.Type。不幸的是,我不能将其更改为

if (t == typeof(RuntimeType))

由于我收到“'RuntimeType' 由于其保护级别而无法访问”的编译器错误。

除了查看 type.Name 或 type.FullName 之外,还有什么方法可以对 RuntimeType 执行类型匹配?

*重新编辑以获得更多说明。

【问题讨论】:

  • 你能给我们更多关于你的代码用例的上下文吗?很难说为什么您的比较总是与您提供给我们的信息返回错误。
  • 好像if (p is Type) {
  • 它用于审计对对象所做的更改。具有该属性的对象中的任何属性都会与之前的状态进行比较,如果它们不同,则会在审核日志中创建一个条目,记录更改内容和更改对象。如果您删除 ...,上面的代码应该可以毫无问题地编译。好吧,除非我在某个地方打错了字。问题的要点是真的“t.Name == "RuntimeType" 很丑(就像 t == typeof(Type).GetType().
  • if (p is Type) { ... } 可能是这样。使用它会导致应用程序目前在代码的其他位置向我抛出运行时错误。我会追上去看看是怎么回事。
  • 猜猜我今天脑子有问题。我不能使用 if (p is Type) 的原因是因为它不仅匹配类型 Type,它还匹配所有其他类型,例如它匹配 typeof(string)。这就是我收到运行时错误的原因。

标签: c#


【解决方案1】:

认为Type 是一个普通类。

Type t1 = typeof(string);
Type t2 = "1".GetType();

t1t2 之间没有区别。什么是t1?只需将t1t2 视为普通对象,对象的类型为System.Type。这意味着t1t2 几乎等于new Type("System.String")

我如何知道对象objStringBuilder

只需使用isas

bool objIsStringBuilder = obj is StringBuilder;

我怎么知道t1Type

同理:

bool t1IsType = t1 is Type;

什么是typeof(Type)t1.GetType()

Type t3 = typeof(Type);

那么t3 几乎等于new Type("System.Type")。所以当然t1t3 是不相等的。

【讨论】:

  • 对不起,如果我理解正确,您是想解释为什么上述方法不起作用?我意识到 Type t 与 t.GetType() 不同。我想我的措辞不够明显?但我最初发布的真正原因是它不可能使用 t == typeof(RuntimeType) 进行匹配,因为它是受保护的。
  • @ThereandThat 为什么要使用RuntimeType?我认为Type t = p as Type; 并检查 t == null 是否足够。
  • p as Type 似乎匹配任何类型的对象,我猜是因为所有对象都有关联的类型。就像 p 是类型一样。它永远不会为空:(
  • @ThereandThat 是的,所有对象都有关联类型,所以p.GetType() 的值始终是Type,而不是对象本身。测试new StringBuilder() is Type.
  • 是的,new StringBuilder() 是返回 null 的类型。但问题是我将未实例化的类的类型存储到一个对象中(object o = typeof(StringBuilder))。然后我检查对象的类型以查看如何处理它。该对象可能根本不是 Type 类型,它可以是任何类型,这就是为什么我需要先检查对象的类型,然后才能对它进行任何操作。之所以会这样,是因为我正在处理一个带有任意参数的属性。与 String.Format("",x,y,z) 类似。
【解决方案2】:

我想我今天早上应该多喝点咖啡或睡一觉。这可行,尽管它似乎与使用 type.FullName 一样错误。

if (t == typeof(Type).GetType()) {
}

哦,好吧。

【讨论】:

  • 我确实说过这似乎是错误的,但是除非您有更好的解决方案,否则为什么要投反对票?
  • t.IsAssignableFrom(typeof(Type)) (msdn.microsoft.com/en-us/library/…) 是否评估为 True
  • 不,t.IsAssignableFrom(typeof(Type)) 不起作用。它也评估为假。
  • 抱歉,我不应该假设。它看起来非常非常错误。虽然它确实产生了正确的结果。类型是类型类型,而不是任意类型。我猜大多数人只是假设(像我一样,哈)
【解决方案3】:

为了测试变量是否为Type 类型,请使用typeof(Type).IsAssignableFrom(x)。如果xtypeof(Type)typeof(RuntimeType),则此表达式返回true,但对于其他类型如typeof(string),则返回false

Type x = typeof(string);
Type y = typeof(Type);
Type z = typeof(Type).GetType(); // RuntimeType

typeof(Type).IsAssignableFrom(x); // false;
typeof(Type).IsAssignableFrom(y); // true;
typeof(Type).IsAssignableFrom(y); // true;

x is Type; // true;
y is Type; // true;
z is Type; // true;

表达式x is Type 的问题在于它会为所有类型(例如typeof(Type)typeof(string))返回true

这有什么用?想象一下,您必须在无法访问原始对象的情况下找到 Type 的类型,例如:

object[] objects = {"hello", typeof(string), 5}; 
Type[] types = objects.Select(x => x.GetType()).ToArray();

// Imagine we are given just the `types` array with a task to get
// indices of types of Type.

for (int i = 0; i < types.Length; ++i) {
  if (typeof(Type).IsAssignableFrom(types[i])) {
    Console.WriteLine($"Object at index {i} is Type!");
  }
}
// prints: "Object at index 1 is Type!"

在对对象进行一些反思并确定字段的值是否为 Type 类型时,我也遇到过这种情况(当类型刚刚传递给我而没有访问原始 FieldInfo 数据时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-31
    • 2012-07-02
    • 2019-07-19
    • 1970-01-01
    • 2015-05-31
    • 2013-05-04
    • 2021-04-24
    • 2019-11-28
    相关资源
    最近更新 更多