Напишите метод расширения, который использует трюк, упомянутый вами в ОБНОВЛЕНИИ:
public static class ObjectExtensions
{
public static T StaticCast<T>(this T o) => o;
}
Для использования:
things.StaticCast<IEnumerable>().GetEnumerator();
Если things
, например, IEnumerable<object>
,это компилируется.Если things
равно object
, произойдет сбой.
// 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();
Зачем использовать статическое приведение?
Одной из распространенных практик при рефакторинге является продолжение и внесение изменений, а затем проверкаВаши изменения не вызвали каких-либо регрессов.Вы можете обнаружить регрессии различными способами и на разных этапах.Например, некоторые типы рефакторинга могут привести к изменениям / поломкам API и потребовать рефакторинга других частей кодовой базы.
Если одна часть вашего кода ожидает получить тип (ClassA
), который должен быть известен приВремя компиляции для реализации интерфейса (IInterfaceA
) и того, что код хочет получить непосредственный доступ к элементам интерфейса, может потребоваться привести к типу интерфейса, например, для доступа к явно реализованным элементам интерфейса.Если после рефакторинга ClassA
больше не реализует IIterfaceA
, вы получите различные типы ошибок в зависимости от того, как вы преобразовали интерфейс:
- приведение в стиле C:
((IInterfaceA)MethodReturningClassA()).Act();
внезапно станет приведением во время выполнения и выдаст ошибку времени выполнения. - Присвоение переменной с явным типом:
IInterfaceA a = MethodReturningClassA(); a.Act();
вызовет ошибку времени компиляции. - Использование
static_cast<T>
-подобный метод расширения: MethodReturningClassA().StaticCast<IInterfaceA>().Act();
вызовет ошибку времени компиляции.
Если вы ожидали, что ваше приведение будет унылым и будет проверяемым во время компиляции, то вам следует использовать метод приведения, который вызывает проверку во время компиляции,Это делает намерения исходного разработчика кода писать типобезопасный код понятным.А написание типобезопасного кода имеет то преимущество, что он более проверяем во время компиляции.Проделав небольшую работу, чтобы прояснить свое намерение включить безопасность типов как для других разработчиков, так и для самого себя, и для компилятора, вы волшебным образом получите помощь компилятора в проверке вашего кода и можете уловить последствия рефакторинга раньше (во время компиляции), чем позже (например, сбой во время выполнения, если ваш код не имеет полного тестового покрытия).