2015-09-08 3 views
0

Если вы проверяете объект для его типа и узнаете, что он относится к типу, который вы проверяли, и вы его преобразовываете в этот тип, может ли этот тип по-прежнему оставаться нулевым после преобразования?Если объект указанного типа, может ли он быть еще нулевым?

Качество сканирования приложение код, который я бегу жалуется следующее:

if (tx.Tag is ExtendedNodeInfo && ty.Tag is ExtendedNodeInfo) 
{ 
    var tagX = tx.Tag as ExtendedNodeInfo; 
    var tagY = ty.Tag as ExtendedNodeInfo;           
    // HP Fortify scan says the below line's use of tagX/Y can be null. 
    // If I add null checks below for taX/Y, Resharper says 
    // its redundant as its always not null 
    return tagX.Ordinal.CompareTo(tagY.Ordinal); 
} 
+0

'tagX/Y'' может быть нулевым, что я вижу –

+2

Возможно, Ординал имеет значение null? –

+0

Если значение tx.Tag равно null, это приведет к отказу первого условия, поэтому ненулевая проверка будет ненужной, в результате чего Resharper отметит это. Но возможно, что tagX/tagY_technically_ может быть нулевым, что заставляет Fortify отмечать его. Попробуйте поместить нулевую проверку вокруг фрагмента кода - это может быть как счастливым. например 'if (tx.Tag! = null && ty.Tag! = null) {' – Ulric

ответ

7

Если tx.Tag не меняет своего значения, это нормально - но предположительно сканер качество кода не знает, что. Как правило, лучше использовать as для этого, так что вы только оценить свойство один раз, только выполнить тест типа один раз, а затем просто проверить ссылки:

var tagX = tx.Tag as ExtendedNodeInfo; 
var tagY = ty.Tag as ExtendedNodeInfo; 
if (tagX != null && tagY != null) 
{ 
    return tagX.Ordinal.CompareTo(tagY.Ordinal); 
} 
+0

Просто для дополнения , когда вы используете конвертер «as», ваша переменная будет равна null, если она не сможет конвертироваться. Вот почему она говорит, что она может быть нулевой. – Luiz

+0

@Luiz, но почему конверсия с 'as' не удалась? – jeroenh

+1

@JonSkeet Хотя я согласны с тем, что предпочтительнее использовать 'as' и проверять значение null, написанный код является абсолютно допустимым и не должен генерировать это предупреждение, IMO – jeroenh

0
if (tx.Tag is ExtendedNodeInfo && ty.Tag is ExtendedNodeInfo) 

После этой линии, у вас есть следующие гарантии:

  • tx и ty не пусто (в противном случае NullReferenceException был бы выброшен)
  • как tx.Tag и ty.Tag имеют тип ExtendedNodeInfo, так что вы можете спокойно бросить их к этому типу, так что в вашем примере как tagX и tagY являются guarantueed быть не нулевым

Если предупреждение об использовании txTag или tyTag, то это неверно, ИМО. Но, возможно, предупреждение о неконтролируемом разыменовании Ordinal?

+1

Или, точнее, и я подозреваю, что здесь появляется предупреждение: «После этой строки * assumin g никакой другой поток не записывает в tx.Tag или ty.Tag *, у вас есть следующие гарантии ». Я не знаю, использует ли какой-либо продукт, который использует OP, с учетом потоков. –

+2

@WillemvanRumpt: Это даже не нужно писать в 'tx.Tag' - это просто должно быть свойство, возвращающее другое значение. Он может возвращать случайное значение каждый раз, когда к нему обращаются :) –

+0

@JonSkeet: Действительно. Вы пытаетесь избежать крошечных ногтей на дороге, забывая взглянуть на массивный большой камень перед вами :) –

Смежные вопросы