Какой смысл ключевого слова «как» в C # - PullRequest
55 голосов
/ 01 июля 2010

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

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

   expression as type

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

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

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

Так почему бы вам не сделать это так или иначе? Почему две системы литья?

Ответы [ 7 ]

81 голосов
/ 01 июля 2010

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

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

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

См. Мою статью на эту тему для получения дополнительной информации.

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

12 голосов
/ 01 июля 2010

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

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

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

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

11 голосов
/ 01 июля 2010

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

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

7 голосов
/ 01 июля 2010

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

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

2 голосов
/ 01 июля 2010

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

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 голосов
/ 01 июля 2010

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

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

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

0 голосов
/ 01 июля 2010

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

// 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...