Unexpected behavior of "as" operator, it differs from plain cast
.net, c#, casting
Solution
It says in the C# Language Specification (emphasis mine),
If the compile-time type of E is not dynamic, the operation E as T produces the same result as E is T ? (T)(E) : (T)null except that E is only evaluated once. The compiler can be expected to optimize E as T to perform at most one dynamic type check as opposed to the two dynamic type checks implied by the expansion above.
If the compile-time type of E is `dynamic`, unlike the cast operator the `as` operator is not dynamically bound (§7.2.2). Therefore the expansion in this case is: `E is T ? (T)(object)(E) : (T)null`
This seems to be the reason why the compilation succeed using `as` or when `this` is cast to an object first. Furthermore,
In an operation of the form `E as T`, `E` must be an expression and `T` must be a reference type, a type parameter known to be a reference type, or a nullable type. Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:
• An identity (§6.1.1), implicit nullable (§6.1.4), implicit reference (§6.1.6), boxing (§6.1.7), explicit nullable (§6.2.3), explicit reference (§6.2.4), or unboxing (§6.2.5) conversion exists from `E` to `T`.
• The type of `E` or `T` is an open type.
• `E` is the `null` literal.
Which is the current case with your generic class.
Problem
I asked this question. This code doesn't compile ("Cannot convert `Generic<T>` to `T`") because of the reason explained here (even if I'd expect an `InvalidCastException` at run-time instead of a compile-time error). ``` class NonGeneric { } class Generic<T> : NonGeneric where T : NonGeneric { T DoSomething() { return (T)this; // ** Cannot convert... } } ``` Accepted solution gave this workaround: ``` T DoSomething() { return this as T; } ``` My question is: why? `as` operator should be exactly equivalent to cast operator: The as operator is like a cast operation. However, if the conversion isn't possible, as returns null instead of raising an exception. If `this as T` should be equivalent to `this is T? (T)this: (T)null` then why `as T` works and `(T)this` doesn't even compile? AFAIK cast could be used in a more wide range of situations than `as`: Note that the as operator performs only reference conversions, nullable conversions, and boxing conversions. The as operator can't perform other conversions, such as user-defined conversions, which should instead be performed by using cast expressions. Then why this? Is it a documented feature of `as` operator? Is it a compiler/language limitation with generic types? Note that this code compiles fine: ``` return (T)((object)this); ``` Is this because compiler can't be sure if `T` is `dynamic` (even if there is a `where` constraint) then it'll always generate such code?