Имеет смысл использовать "в качестве" вместо броска, даже если нет никакой пустой проверки? [закрытый]

В блогах разработки, примерах кода онлайн и (недавно) даже книге, я продолжаю спотыкаться о коде как это:

var y = x as T;
y.SomeMethod();

или, еще хуже:

(x as T).SomeMethod();

Это не имеет смысла мне. Если Вы уверены это x имеет тип T, необходимо использовать прямой бросок: (T)x. Если Вы не уверены, можно использовать as но должен проверить на null прежде, чем выполнить некоторую операцию. Все, что делает вышеупомянутый код, должно стать (полезным) InvalidCastException в (бесполезный) NullReferenceException.

Действительно ли я - единственный, кто думает что это явное злоупотребление as ключевое слово? Или я пропускал что-то очевидное, и вышеупомянутый шаблон на самом деле имеет смысл?

350
задан Heinzi 30 March 2014 в 20:28
поделиться

13 ответов

Ваше понимание верно. Это звучит так, как пытаться использовать мне микро-оптимизировать. Вы должны использовать нормальный отрыв, когда вы уверены в типе. Помимо генерации более разумного исключения, он также не удается быстро. Если вы не правы о своем предположении о типе, ваша программа немедленно потерпит неудачу, и вы сможете увидеть причину сбоя сразу же, а не в ожидании NullReferenceException или ArgumentNullexception Или даже логическая ошибка когда-то в будущем. В целом as выражение , которое не сопровождается NULL , проверяет где-то, является кодовым запахом.

С другой стороны, если вы не уверены в тому, и ожидаете, что он не сможет использовать, вы должны использовать как вместо нормального состава, завернутого Try-Catch блок Отказ Более того, использование как рекомендуется по поводу проверки типа, с которым следуют актером. Вместо:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

, которые генерируют инструкцию ISINST для ключевого слова , а также CastClass для активов (эффективно выполняя Выделение дважды), вы должны использовать:

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

Это только генерирует инструкцию ISINST . Бывший метод имеет потенциальный недостаток в многопотативных приложениях, поскольку состояние гонки может привести к изменению ее типа после того, как - это , проверяется, и сбой на линию. Последний метод не подвержен этой ошибке.


Следующее решение не рекомендуется для использования в производстве. Если вы действительно ненавидите такую ​​фундаментальную конструкцию в C #, вы можете рассмотреть возможность переключения на VB или другой язык.

В случае, если кто-то отчаянно ненавидит литой синтаксис, он / она может написать метод расширения, чтобы имитировать актеры:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

и использовать аккуратный [?] Синтаксис:

obj.To<SomeType>().SomeMethod()
251
ответ дан 23 November 2019 в 00:26
поделиться

Прямые литые нужны пару круглых скобок больше, чем как ключевое слово . Так что даже в том случае, если вы на 100% уверены, что такое тип, это уменьшает визуальный беспорядок.

Договорились о исключительной вещи, хотя. Но, по крайней мере, для меня, большинство применений как откидывается, чтобы проверить NULL , которые я нахожу присяга, чем ловить исключение.

11
ответ дан 23 November 2019 в 00:26
поделиться

Обратный вызов позволяет передавать исполняемый код в качестве аргумента другому коду. В C и C++ это реализовано как указатель функции. В .NET для управления указателями функций используется делегат.

Некоторые применения включают в себя сигнализацию об ошибках и управление тем, действует ли функция.

Википедия

-121--689976-

Глава 4 практики программирования дала как C, так и C++ реализации анализатора CSV.

-121--4213511-

Я считаю, что ключевое слово как можно рассматривать как более элегантную версию dynamic _ cast из C++.

2
ответ дан 23 November 2019 в 00:26
поделиться

Одна причина использования «как»:

T t = obj as T;
 //some other thread changes obj to another type...
if (t != null) action(t); //still works

вместо (плохого кода):

if (obj is T)
{
     //bang, some other thread changes obj to another type...
     action((T)obj); //InvalidCastException
}
1
ответ дан 23 November 2019 в 00:26
поделиться

Просто потому, что людям нравится, как она выглядит, она очень читаема.

Посмотрим правде в глаза: оператор литья/преобразования на C-подобных языках довольно ужасен, удобочитаем. Я хотел бы, чтобы лучше, если C # принял либо Javascript синтаксис:

object o = 1;
int i = int(o);

Или определите оператор - , эквивалент литья как :

object o = 1;
int i = o to int;
-121--25624-

В _ cleanUpTaskFactory можно просто сделать следующее:

var mocks = new List<Mock<ITask>>();
for(var i = 0; i < 10; i++){
    var mock = new Mock<ITask>();
    mock.Setup(t => t.Execute()).Verifiable();
    mocks.Add(mock);
}

_cleanUpTaskFactoryMock.Setup(f => f.GetTasks()).Returns(mocks.Select(m => m.Object).Tolist());

Теперь обязательно сохраняйте ссылку на список mocks , и по завершении тестирования выполните итерацию над всеми mocks и вызовите Verify () так:

mocks.ForEach(m => m.Verify());
-121--1906259-

Он, вероятно, более популярен без технической причины, но только потому, что его легче читать и он более интуитивно понятен. (Не говоря, что это делает лучше просто попытаться ответить на вопрос)

1
ответ дан 23 November 2019 в 00:26
поделиться

99% случаев, когда я использую «как», когда я не уверен, какой фактический тип объекта

var x = obj as T;
if(x != null){
 //x was type T!
}

, и я не хочу уловить явные исключения от литых, ни сделать линие дважды, используя «IS»:

//I don't like this
if(obj is T){
  var x = (T)obj; 
}
8
ответ дан 23 November 2019 в 00:26
поделиться

ИМХО, Как просто имеет смысл в сочетании с NULL . Проверка:

var y = x as T;
if (y != null)
    y.SomeMethod();
42
ответ дан 23 November 2019 в 00:26
поделиться

Я немного написал об этом здесь:

http://blogs.msdn.com/iclelippert/archive/2009/10/08/what-s-difference-betweetween-as операторы.aspx

Я понимаю вашу точку зрения. И я согласен с толчком этого: то, что актерский оператор связывается «Я уверен, что этот объект может быть преобразован в этот тип, и я готов рисковать исключением, если я ошибаюсь», тогда как оператор «как» сообщает оператор «Я не уверен, что этот объект может быть преобразован в этот тип; дай мне нуль, если я ошибаюсь».

Однако есть тонкое значение. (x as t) .whatever () связывается "Я знаю не только то, что x можно преобразовать в t, но, кроме того, что делает это, включает в себя только преобразование ссылок или распаковки, и, кроме того, что X не является NULL». Это сообщает разные информации, чем ((t) x) .whatever (), и, возможно, именно то, что автор кода намеревается.

36
ответ дан 23 November 2019 в 00:26
поделиться

Это только потому, что люди любят, как это выглядит, это очень читается.

Давайте поставим к себе: оператор отливки / преобразования в C-подобных языках довольно ужасна, читаемость - мудрый. Я хотел бы лучше, если C # принял либо синтаксис JavaScript:

object o = 1;
int i = int(o);

или определить к оператору , эквивалент кастинга как :

object o = 1;
int i = o to int;
8
ответ дан 23 November 2019 в 00:26
поделиться

Это должно быть одним из моих главных мозолей .

STROUSTRUP'S D & E и / или некоторые сообщения в блоге я не могу найти прямо сейчас обсуждает понятие оператора к , который обратился бы к точке, сделанной https://stackoverflow.com/users/7307070 / Йоханнес-Россель (т. Е. То же синтаксис как как , но с DirectCak семантика).

Причина, по которой эта не была реализована, заключается в том, что актерский актер должен привести к боли и быть уродливым, поэтому вы отталкиваетесь от этого.

Жаль, что «умные» программисты (часто книжные авторы (Juval Lowy IIRC)) шагают вокруг этого, злоупотребляя как в этой моде (C ++ не предлагает как , возможно, для этого причина).

Даже VB имеет более согласованность в том, чтобы иметь единый синтаксис, который заставляет вас выбрать Trycast или DirectCast и составляют свой разум !

5
ответ дан 23 November 2019 в 00:26
поделиться

Люди любят как так, потому что это заставляет их чувствовать себя в безопасности от исключений... Как гарантия на коробку. Парень кладет на коробку модную гарантию, потому что хочет, чтобы ты чувствовала тепло и тостику внутри. Ты думаешь, что положил эту коробку под подушку ночью, Гарантийная Фея может спуститься и уйти на четверть, я прав Тед?

Вернемся к теме... при использовании прямого приведения существует возможность для недопустимого исключения приведения. Таким образом, люди применяют как в качестве общего решения для всех своих потребностей в литье, потому что как (само по себе) никогда не вызовет исключения. Но самое забавное в этом, это в примере, который вы дали (x как T) .SomeMethod (); вы торгуете недопустимым исключением литья для нулевого ссылочного исключения. Что запутывает реальную проблему, когда вы видите исключение.

Я обычно не использую как слишком много. Я предпочитаю, чтобы был тестом, потому что для меня он кажется более читаемым и имеет больше смысла, чем попытка приведения и проверка на нулевое значение.

-121--525625-
<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

внутри литерала последовательности завершает весь сценарий, чтобы избежать использования «» .

-121--560448-

Я часто видел ссылки на эту вводящую в заблуждение статью как доказательство того, что «как» быстрее, чем литье.

Одним из наиболее очевидных вводящих в заблуждение аспектов этой статьи является графика, которая не показывает, что измеряется: я подозреваю, что это измерение неудачных слепков (где «как», очевидно, гораздо быстрее, так как не выбрасывается исключение).

Если вы берете время, чтобы сделать измерения, то вы увидите, что литье, как вы ожидали, быстрее , чем «как», когда литье успешно.

Я подозреваю, что это может быть одной из причин использования «cargo cult» в качестве ключевого слова вместо приведения.

16
ответ дан 23 November 2019 в 00:26
поделиться

Использование «AS» не применяет определенные пользовательские преобразования, в то время как актеры будут использовать их, где это необходимо. Это может быть важной разницей в некоторых случаях.

39
ответ дан 23 November 2019 в 00:26
поделиться

Людям нравится как , потому что это заставляет их чувствовать себя в безопасности от исключений ... Как гарантия на коробке. Парень дает на коробку причудливую гарантию, потому что хочет, чтобы внутри вас было тепло и жарко. Вы полагаете, что кладете эту коробочку себе под подушку на ночь, Фея Гарантии может спуститься и оставить четвертак, я прав, Тед?

Вернемся к теме ... при использовании прямого приведения существует возможность недопустимого исключения приведения типов. Таким образом, люди применяют как в качестве общего решения для всех своих задач приведения типов, потому что как (сам по себе) никогда не вызовет исключения. Но самое забавное в том, что в примере, который вы указали (x as T) .SomeMethod (); , вы обмениваете недопустимое исключение приведения типов для исключения нулевой ссылки. Что скрывает реальную проблему, когда вы видите исключение.

Я обычно не использую как слишком часто. Я предпочитаю тест is , потому что мне он кажется более читаемым и имеет больший смысл, чем попытка приведения и проверка на null.

5
ответ дан 23 November 2019 в 00:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: