Чи може нульовий посилальний тип у C # 8 бути недійсним під час виконання?


10

Мені здається, насправді немає гарантії того, що незмінна змінна ніколи не матиме нульового значення. Уявіть, що у мене клас, який має одну властивість, яку не можна звести нанівець:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

Тепер це може здатися, що це зараз не може бути нульовим. Але якщо ми посилаємо цей клас на іншу бібліотеку, яка не використовує зведений контекст, ніщо не заважає йому надсилати нуль туди.

Це правильно чи є деякі перевірки часу виконання, а також, можливо, що забезпечують це?


Це public void Foo(string test){...}чи public Foo(string test){...}?
huMpty duMpty

Дякую, я це виправив. Ось що відбувається, коли людина занадто багато покладається на R # для створення конструкторів :)
Ілля Чорномордик

2
C # 9 (ймовірно) додасть спрощену нульову перевірку .
Стівен

Коротше кажучи, функція "зведених довідкових типів" повністю порушена.
Алехандро

Відповіді:


9

Про це говорить MS ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

Компілятор не може перевірити всі виклики до ваших загальнодоступних API, навіть якщо ваш код зібраний із включеними контекстами анулювання. Крім того, ваші бібліотеки можуть споживатися проектами, які ще не вирішили використовувати зведені типи посилань. Перевірте вхідні дані для загальнодоступних API, навіть якщо ви оголосили їх як невідмінні типи.


2

хтось завжди може це зробити

var myFoo = new Foo(null);

Можливо, ви можете використовувати дизайн, керований доменом

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}

так, ти маєш рацію, я думаю, це все одно лише попередження. Я сподіваюсь, що в майбутньому вони дійсно зможуть це застосувати якось, як, наприклад, у Котлін
Ілля Чорномордик

2

Ви правильні, інший код, який не використовує нову функцію, може призначити цю властивість нульовою, немає перевірок під час виконання, це лише підказки.

Ви завжди можете зробити це самостійно, якщо хочете перевірити час виконання:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

Зверніть увагу, що ви можете гарантувати, що не буде нульовим у більшості свого коду, вам просто потрібно додати гвардії до свого верхніх версій Public API і переконатися, що класи належним чином запечатані тощо.

Звичайно, люди все ще можуть використовувати відображення для f *** вашого коду, але потім його на них


Отже, це фактично означає, що я все ще можу отримати Null Reference Exception, навіть якщо я використовую нерегульований тип, правда?
Ілля Чорномордик

Ну .... ви не можете в коді, який ви компілюєте, тому що у вас є підказки на ... але код інших народів, на який немає підказки, але посилається на ваш код - так, вони можуть отримати нульовий виняток
Мілней

Ну, якщо, наприклад, автомат використовує ваш конструктор, або щось подібне, ви виняток отримаєте все-таки :)
Ілля Черномордик

Of course people can still use reflection to f*** your code up, правда, справді справді. Ви , безумовно , можна використовувати відображення , щоб зробити це, це не рекомендується , немає , робити люди до сих пір зробити це, так.
Çöđěxěŕ

2

Навіть у власному коді, якщо ви вирішите це зробити, ви можете пройти null, скориставшись оператором, що прощає нуль. null!що стосується аналізу зведеності на зразок компілятора, він вважається недійсним.


-1

Для вирішення питання про нульові перевірки, а також для того, щоб зробити ваш код читабельним, я пропоную шаблон з нульовим дизайном об’єктів.

Більше читання тут:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

В основному, це включає створення нового об'єкта, який є похідним від того ж інтерфейсу і має нульовий екземпляр.

Приклад:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

Нуль не уникнути, проте їх можна перевірити чисто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.