Какой смысл “Как” ключевое слово в C#

Из документов:

Поскольку оператор похож на бросок за исключением того, что он приводит к пустому указателю при отказе преобразования вместо того, чтобы повысить исключение. Более официально, выражение формы:

   expression as type

эквивалентно:

  expression is type ? (type)expression : (type) null

за исключением того, что выражение оценено только однажды.

Итак, почему Вы не выбрали бы ни одному, делают это так или иначе. Почему имеют две системы кастинга?

55
задан Mark Cidade 30 July 2010 в 17:52
поделиться

7 ответов

Это не две системы кастинга. У этих двоих похожие действия, но очень разные значения. «As» означает «я думаю, что этот объект может действительно принадлежать к этому другому типу; дайте мне null, если это не так». Приведение означает одно из двух:

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

  • Я точно знаю, что этот объект не принадлежит к другому типу, но существует хорошо известный способ преобразования значения текущего типа в желаемый тип. (Например, приведение int к short.) Сделайте это так, и если преобразование на самом деле не работает, завершите программу.

Подробнее см. В моей статье на эту тему.

http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

81
ответ дан 7 November 2019 в 07:14
поделиться

Это позволяет выполнять быструю проверку без накладных расходов на попытку / приведение, что может быть необходимо в некоторых случаях для обрабатывать деревья наследования на основе сообщений.

Я использую его довольно часто (попасть в сообщение, реагировать на определенные подтипы). Try / cast будет значительно медленнее (много кадров try / catch в каждом проходящем сообщении) - и здесь мы говорим об обработке 200 000 сообщений в секунду.

7
ответ дан 7 November 2019 в 07:14
поделиться

Я обычно выбираю один или другой в зависимости от семантики кода.

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

Используйте как , если вы не уверены, что объект относится к определенному типу, но хотите иметь логику, когда это так. Вы можете использовать оператор is , за которым следует приведение, но оператор as более эффективен.

2
ответ дан 7 November 2019 в 07:14
поделиться

Эффективность и производительность

Частью выполнения приведения является интегрированная проверка типов; поэтому префикс фактического приведения с явной проверкой типов является избыточным (проверка типов происходит дважды). Использование ключевого слова as гарантирует, что будет выполнена только одна проверка типов. Вы можете подумать: "Но это же проверка нуля вместо второй проверки типа", но проверка нуля очень эффективна и производительна по сравнению с проверкой типа.

if (x is SomeType )
{
  SomeType y = (SomeType )x;
  // Do something
}

делает 2 раза проверку, тогда как

SomeType y = x as SomeType;
if (y != null)
{
  // Do something
}

делает 1 раз - проверка нуля очень дешева по сравнению с проверкой типов.

12
ответ дан 7 November 2019 в 07:14
поделиться

Потому что иногда вы хотите, чтобы вещи не работали, если вы не можете кастовать, как вы ожидаете, а иногда вам все равно, и вы просто хотите отбросить данный объект, если он не может кастовать.

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

12
ответ дан 7 November 2019 в 07:14
поделиться

Может быть, примеры помогут:

// Regular casting
Class1 x = new Class1();
Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2

// Casting with as
Class2 y = x as Class2; // Sets y to null if it can't be casted.  Does not work with int to short, for example.

if (y != null)
{
  // We can use y
}

// Casting but checking before.
// Only works when boxing/unboxing or casting to base classes/interfaces
if (x is Class2)
{
  y = (Class2)x; // Won't fail since we already checked it
  // Use y
}

// Casting with try/catch
// Works with int to short, for example.  Same as "as"
try
{
  y = (Class2)x;
  // Use y
}
catch (InvalidCastException ex)
{
  // Failed cast
}
0
ответ дан 7 November 2019 в 07:14
поделиться

Позвольте мне представить вам реальные сценарии, в которых вы могли бы использовать и то, и другое.

public class Foo
{
  private int m_Member;

  public override bool Equals(object obj)
  {
    // We use 'as' because we are not certain of the type.
    var that = obj as Foo;
    if (that != null)
    {
      return this.m_Member == that.m_Member;
    }
    return false;   
  }
}

И ...

public class Program
{
  public static void Main()
  {
    var form = new Form();
    form.Load += Form_Load;
    Application.Run(form);
  }

  private static void Form_Load(object sender, EventArgs args)
  {
    // We use an explicit cast here because we are certain of the type
    // and we want an exception to be thrown if someone attempts to use
    // this method in context where sender is not a Form.
    var form = (Form)sender;

  }
}
2
ответ дан 7 November 2019 в 07:14
поделиться
Другие вопросы по тегам:

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