Как отличить System.Array в Generic для ввода T [duplicate]

Это означает, что указанная переменная не указана ни на что. Я мог бы сгенерировать это так:

SqlConnection connection = null;
connection.Open();

Это вызовет ошибку, потому что, пока я объявил переменную «connection», она не указала ни на что. Когда я пытаюсь вызвать член «Open», для его устранения нет ссылки, и он будет вызывать ошибку.

Чтобы избежать этой ошибки:

  1. Всегда инициализируйте свои объекты, прежде чем пытаться что-либо с ними делать.
  2. Если вы не уверены, что объект имеет значение null, проверьте его с помощью object == null.

Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам ввести нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.

31
задан Incognito 20 June 2011 в 06:12
поделиться

2 ответа

В принципе наследования C # интерфейсы могут наследоваться несколько раз, но класс один раз. Поскольку наследование от интерфейсов имеет сложную иерархию, инфраструктуре .net не нужно обеспечивать общий тип T конкретным интерфейсом во время компиляции. (EDIT). Напротив, классу может быть обеспечен определенный класс с объявлением ограничения типа при компиляции в виде следующего кода.

class MyClass<T> where T : SomeClass
{
   void SomeMethod(T t)
   {
      ISomeInterface obj1 = (ISomeInterface)t;
      SomeClass      obj2 = (SomeClass)t;     
   }
}
2
ответ дан Jin-Wook Chung 27 August 2018 в 14:07
поделиться

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

Опции:

  • Сначала перенесите объект:
    SomeClass obj2 = (SomeClass) (object) t;
    
  • Вместо этого используйте as:
    SomeClass obj2 = t as SomeClass;
    

Очевидно во втором случае вам также понадобится выполнить проверку недействительности позже, если t - not a SomeClass.

EDIT: аргументы для этого приведены в разделе 6.2.7 спецификации C # 4:

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

class X<T>
{
    public static long F(T t) {
        return (long)t; // Error 
    }
} 

Если разрешено прямое явное преобразование t в int, можно легко ожидать, что X<int>.F(7) вернет 7L. Однако это не так, потому что стандартные числовые преобразования учитываются только тогда, когда типы известны как числовые во время привязки. Чтобы сделать семантику понятной, вместо этого должен быть написан вышеприведенный пример:

class X<T>
{
    public static long F(T t) {
        return (long)(object)t; // Ok, but will only work when T is long
    }
}

Этот код теперь будет компилироваться, но выполнение X<int>.F(7) затем выдаст исключение во время выполнения, так как вложенное значение int не может быть преобразован непосредственно в длинный.

43
ответ дан Jon Skeet 27 August 2018 в 14:07
поделиться
Другие вопросы по тегам:

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