typeof(T) vs new T().GetType() 可以翻译为: typeof(T) 与 new T().GetType()

huangapple go评论51阅读模式
英文:

typeof(T) vs new T().GetType()

问题

以下是您要翻译的内容:

这两个表达式是否保证完全相同?

在泛型方法Foo<T> where T : new()中,这个表达式是否始终为true

typeof(T) == new T().GetType()

我不明白它怎么可能为false,但也许我错过了一些边缘情况。

我认为这并未在以下相关问题中得到解答:

英文:

Are the two expressions guaranteed to be identical?

In a generic method Foo<T> where T : new() ... is this expression always true?

typeof(T) == new T().GetType()

I don't see how it could be false, but perhaps I'm missing an edge-case.

I don't think this is addressed in any of the following related questions:

答案1

得分: 7

typeof(T)new T().GetType() 不完全相同。实际上,new T().GetType() 不是“安全”的。

考虑当 Tint? 或类似的类型时,new T() 将导致 null - 实际上是一个具有 HasValue = falseint? 实例,它实际上是一个结构体。对一个没有值的可空值类型进行装箱会导致 null,并且调用继承自 object 的方法将首先装箱该值。因此,在这种情况下,new T().GetType() 会引发空引用异常。

这个表达式是否始终为真
typeof(T) == new T().GetType()

这可能是永远不会为假(要么为真,要么不会计算出一个值),但我可能忽略了一些其他奇怪的边缘情况。

英文:

typeof(T) and new T().GetType() are not quite identical. In fact, new T().GetType() is not "safe".

Consider when T is an int? or something similar, then new T() will result in null - actually an instance of int? with HasValue = false, which is actually a struct. Boxing a nullable value type that has no value results in null, and calling a method on it that is inherited from object will box the value first. So new T().GetType() throws a null reference exception in this case.

> is this expression always true
> typeof(T) == new T().GetType()

It might be that it is never false (ie either true or does not evaluate to a value), but I may be overlooking some other strange edge case.

答案2

得分: 2

很遗憾,不是这样的。对于具有默认构造函数的引用类型(包括可空引用类型),是的,但对于可空值类型不成立。

Tint?DateTime?或任何其他可空值类型时,new T()的结果是null。在null上调用GetType()当然会导致NullReferenceException异常。但让我们尝试一些其他方式:

static Type? WhichType<T>(T value) => value?.GetType();

这不会引发异常,但可能返回null。现在让我们试试:

var type1 = WhichType<int?>(0);
var type2 = WhichType((int?)0);

由于可空值类型在C#编译器中受到特殊处理,调用可空值类型上的GetType()是否会返回内部类型并不完全清楚,这在某种程度上是有道理的。但遗憾的是,当有人使用错误的类型调用您的通用方法时,它并不能帮助您太多。

而且,如果你想比较一个值的类型与预期类型,其中T是可空值类型,可能会出现问题。在这种情况下,您需要使用一些代码来解决问题。

var targetType = typeof(T);
if (targetType.IsConstructedGenericType &&
    targetType.GetGenericTypeDefinition() == typeof(Nullable<>)
)
    targetType = Nullable.GetUnderlyingType(targetType);

这将根据需要从外部类型中解开Nullable<>,允许您将其与对象实例类型进行比较。

英文:

> In a generic method Foo&lt;T&gt; where T : new() ... is this expression always true?
>
> typeof(T) == new T().GetType()

Sadly, no. For reference types (including nullable reference types) with default constructors then yes, but this doesn't hold true for nullable value types.

Where T is int? or DateTime? or any other nullable value type, the result of new T() is null. Calling GetType() on null is of course going to result in a NullReferenceException. But let's try something else:

static Type? WhichType&lt;T&gt;(T value) =&gt; value?.GetType();

This won't throw an exception, but may return null. Now let's try it out:

var type1 = WhichType&lt;int?&gt;(0);
var type2 = WhichType((int?)0);

Since nullable value types are treated specially by the C# compiler, it's not entirely clear that the result of calling GetType() on a nullable value type will return the inner type, and it makes some sense. Sadly it doesn't help you much when someone calls your generic method with the wrong type.

And in case you're wondering, it works on any value type not just value primitives:

public struct TestType { }

var type1 = WhichType&lt;DateTime?&gt;(DateTime.Now);
var type2 = WhichType&lt;TestType?&gt;(new TestType());

Where this may be an issue is when you're trying to compare the type of a value with an expected type where T is a nullable value type. In this case you need to use a bit of code to figure things out.

var targetType = typeof(T);
if (targetType.IsConstructedGenericType &amp;&amp;
    targetType.GetGenericTypeDefinition() == typeof(Nullable&lt;&gt;)
)
    targetType = Nullable.GetUnderlyingType(targetType);

This will unwrap the Nullable&lt;&gt; from the outer type if necessary, allowing you to compare it to the an object instance type.

答案3

得分: 0

这段代码的大意是讨论了在不同情况下,使用 GetType()typeof(T) 这两种方式获取类型信息可能会得到不同的结果。在代码中提到了如果 T 是一个非抽象类并且有一个子类 R,那么使用 GetType() 会返回实际运行时的类型,而 typeof(T) 返回的是编译时的类型。最后,代码展示了在不同情况下,使用这两种方式获取类型信息的结果可能会不同。

英文:

It depends what you mean. If you are instantiating T (your var x = new T();) and then immediately after writing

Type t1 =  x.GetType();

and

if (t1 == typeof(T)) {... } // probably always true by definition

but what if your T is say a non abstract class and has subclass R? Well that changes the picture, doesn't it? I mean GetType() is a run time type (not a static compile type like typeof(T)). So (pseudo-code here below)

var x = new T();
var t1 = x.GetType(); // T 
...
x = new R();
...
bool chk1 = t1 == typeof(T); // true;
t1 = x.GetType(); // R
bool chk2 = t1 == typeof(T); // false

答案4

得分: -1

我认为它们始终提供相同的结果。不同之处在于,对于 typeof,您不必创建一个新的 T 实例,这实际上是一件好事。此外,如果您使用 typeof 来检查类型,从语义上来说更加明显,而不是创建一个对象的实例。

英文:

I suppose they're always provide the same result. The difference is in that for typeof you don't have to create new instance of a T which is rather something good.
Also it's semantically more obvious if you go with typeof to check type rather than creating instance of an object.

huangapple
  • 本文由 发表于 2023年5月29日 20:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76357585.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定