Given a couple types like this:
interface I {}
class C : I {}
How can I do a static type cast? By this I mean: how can I change its type in
If you're really just looking for a way to see if an object implements a specific type, you should use as
.
I i = whatever as i;
if (i == null) // It wasn't
Otherwise, you just cast it. (There aren't really multiple types of casting in .NET like there are in C++ -- unless you get deeper than most people need to, but then it's more about WeakReference and such things.)
I i = (I)c;
If you're just looking for a convenient way to turn anything implementing I
into an I
, then you could use an extension method or something similar.
public static I ToI(this I @this)
{
return @this;
}
Write an extension method that uses the trick you mentioned in your UPDATE:
public static class ObjectExtensions
{
public static T StaticCast<T>(this T o) => o;
}
To use:
things.StaticCast<IEnumerable>().GetEnumerator();
If things
is, e.g., IEnumerable<object>
, this compiles. If things
is object
, it fails.
// Compiles (because IEnumerable<char> is known at compiletime
// to be IEnumerable too).
"adsf".StaticCast<IEnumerable>().GetEnumerator();
// error CS1929: 'object' does not contain a definition for 'StaticCast'
// and the best extension method overload
// 'ObjectExtensions.StaticCast<IEnumerable>(IEnumerable)'
// requires a receiver of type 'IEnumerable'
new object().StaticCast<IEnumerable>().GetEnumerator();
One common practice during refactoring is to go ahead and make your changes and then verify that your changes have not caused any regressions. You can detect regressions in various ways and at various stages. For example, some types of refactoring may result in API changes/breakage and require refactoring other parts of the codebase.
If one part of your code expects to receive a type (ClassA
) that should be known at compiletime to implement an interface (IInterfaceA
) and that code wants to access interface members directly, it may have to cast down to the interface type to, e.g., access explicitly implemented interface members. If, after refactoring, ClassA
no longer implements IIterfaceA
, you get different types of errors depending on how you casted down to the interface:
((IInterfaceA)MethodReturningClassA()).Act();
would suddenly become a runtime cast and throw a runtime error.IInterfaceA a = MethodReturningClassA(); a.Act();
would raise a compiletime error.static_cast<T>
-like extension method: MethodReturningClassA().StaticCast<IInterfaceA>().Act();
would raise a compiletime error.If you expected your cast to be a downcast and to be verifiable at compiletime, then you should use a casting method that forces compiletime verification. This makes the intentions of the code’s original developer to write typesafe code clear. And writing typesafe code has the benefit of being more verifiable at compiletime. By doing a little bit of work to clarify your intention to opt into typesafety to both other developers, yourself, and the compiler, you magically get the compiler’s help in verifying your code and can catch repercussions of refactoring earlier (at compiletime) than later (such as a runtime crash if your code didn’t happen to have full test coverage).
Simply cast it:
(I)c
Edit Example:
var c = new C();
((I)c).MethodOnI();
var c = new C();
I i = c; // statically checked
equals to
I i = new C();