Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
 Аватар для PasterLak
0 / 0 / 0
Регистрация: 09.02.2019
Сообщений: 9

== null возвращает неверное значение

14.11.2023, 18:03. Показов 665. Ответов 10

Студворк — интернет-сервис помощи студентам
Добрый день,

пишу свою реализацию Octree для игры, и сталкнулся с проблемой из-за который мой код не корректно работает.

Чтобы коротко описать проблему я написал класс который её хорошо показывает:

Имеется простой Generic класс, который хранит данные.

И есть две функции, одна проверяет на null а другая возвращает данные

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestData<T> 
    {
        private T data;
 
        public TestData(T data)
        {
            this.data = data;
        }
        
        public bool IsDataNull()
        {
            return data == null;
        }
        public T GetData()
        {
            return data;
        }
        
    }

Проблема в том что если я получаю data через GetData() и проверяю на null, то получаю true, то есть что данных нет, хотя они там имеются. Это происходит только с T, если в классе напрямую нужный тип использовать,то всё работает корректно.

Я давно на C# пишу, но я либо туплю, либо у меня какие то пробелы в знаниях и я не совсем понимаю почему сравнение на null в этих 2х случаях работает не одинаково.

C#
1
2
3
4
5
6
TestData<Block> test = new TestData<Block>(b);
         
            
Debug.Log($"Is data null: {test.IsDataNull()}"); //  false
 
Debug.Log($"Is GetData null: { (test.GetData() == null) }");  // true
Буду благодарен если обьясните почему такое происходит

Явное указание через where что T это class тоже не помогло
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.11.2023, 18:03
Ответы с готовыми решениями:

GetProperty() возвращает null как я понял
У меня есть несколько типов репортов и у каждого есть свой пример так скажем switch (tab.Text) { case &quot;Жалобы на...

Извлечение внедрённых ресурсов (GetManifestResourceStream возвращает null)
Здесь скрины исключения и файла ресурса *resx: Странно делаю всё по примерам с msdn, но ничего не выходит,...

System.DirectoryServices.AccountManagement.UserPrincipal.AccountExpirationDate возвращает null
Приветствую всех! Мне нужна помощь по классу UserPrincipal из сборки System.DirectoryServices.AccountManagement.dll. Дело в том, что я...

10
643 / 338 / 139
Регистрация: 19.10.2013
Сообщений: 1,209
14.11.2023, 19:52
переменная b у вас как создается? Если так:
C#
1
Block b = new Block()
b в этом случае не будет равно null, ибо объект создан и проинициализирован

а для того чтобы метод сработал, то сделайте так

C#
1
Block b = null;
0
 Аватар для PasterLak
0 / 0 / 0
Регистрация: 09.02.2019
Сообщений: 9
14.11.2023, 19:57  [ТС]
Да, создаётся через new

C#
1
Block b1 = new Block();
Поэтому я ломаю голову по какой причине происходит такое. Я думаю это связанно с особенностями Generic, но я понятия не имею из-за чего конкретно возвращаемое значение вдруг становится нулевым
0
643 / 338 / 139
Регистрация: 19.10.2013
Сообщений: 1,209
14.11.2023, 20:14
Цитата Сообщение от PasterLak Посмотреть сообщение
Поэтому я ломаю голову по какой причине происходит такое. Я думаю это связанно с особенностями Generic, но я понятия не имею из-за чего конкретно возвращаемое значение вдруг становится нулевым
ой вей, вы прочли мои ответ полностью?
Цитата Сообщение от 116rus Посмотреть сообщение
Block b = new Block()
b в этом случае не будет равно null, ибо объект создан и проинициализирован
Добавлено через 1 минуту
Цитата Сообщение от 116rus Посмотреть сообщение
Я думаю это связанно с особенностями Generic
причем тут generic?
0
 Аватар для PasterLak
0 / 0 / 0
Регистрация: 09.02.2019
Сообщений: 9
14.11.2023, 21:04  [ТС]
Функция IsDataNull() как раз таки возвращает правильный ответ (false), потому что обьект имеется.

(GetData() == null) проверяет по сути тоже самое что и IsDataNull(), но возвращает true, что не верно

Block b = new Block()
b в этом случае не будет равно null, ибо объект создан и проинициализирован
Да так и должно быть. Я и пытаюсь понять почему (GetData() == null) вдруг равно true
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
14.11.2023, 22:00
У меня выдает

Is data null: False
Is GetData null: False
что является верным результатом...
0
 Аватар для PasterLak
0 / 0 / 0
Регистрация: 09.02.2019
Сообщений: 9
14.11.2023, 22:13  [ТС]
У меня выдает

C#
1
2
Is data null: False
Is GetData null: False
что является верным результатом...
Я тоже проверил на чистом C# в VS, там код работает правильно. Выводится false в обоих случаях.

Я нашёл причину когда выводится false true.

Я делаю проект в Unity и класс Block наследуется от MonoBehaviour.
C#
1
public class Block : MonoBehaviour
Там наследование по сути не нужно и когда я его удалил то код начал правильно работать. Не понимаю как наличие наследования тут вызывает такое некорректное выполнение оператора ==. Возможно какой-то новый баг в Unity
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
14.11.2023, 22:39
Цитата Сообщение от PasterLak Посмотреть сообщение
(GetData() == null) проверяет по сути тоже самое что и IsDataNull(), но возвращает true, что не верно
А вы уверены на 146% что GetData() возращает НЕ null? А ещё.... ух, с чего бы начать? =)

Во-первых: <T> без каких либо ограничений. Т.е. это может быть как struct, так и class. А с ними принципиально разные ситуации. class -- сылочный тип, который может быть null (как писали выше), так и существующим объектом.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var test1 = new Test<Neko>(null);
var result1 = test.IsNull; //true
 
var neko = new Neko();
var test2 = new Test<Neko>(neko);
var result2 = test.IsNull; //false
 
class Test<T>(T item)
{
    public T Value { get; } = item;
    public bool IsNull => Value == null;
}
 
class Neko { }
Теперь по структурам. По умолчанию, они не могут быть пустыми, т.е. при инициализации переменной мы всегда создаем экземпляр, даже если укажем default (ну а null нам не даст указать компилятор)

C#
1
2
3
4
5
6
7
8
9
10
11
Neko neko = default;
var test = new Test<Neko>(neko);
var result = test.IsNull; //false
 
class Test<T>(T item)
{
    public T Value { get; } = item;
    public bool IsNull => Value == null;
}
 
struct Neko { }
Исключение -- Nullable (что как бы структура), который имеет перегрузку позволяющую сравнить с null и получить true
C#
1
2
3
4
5
6
7
8
9
10
11
Neko? neko = default;
var test = new Test<Neko?>(neko);
var result = test.IsNull; //true
 
class Test<T>(T item)
{
    public T Value { get; } = item;
    public bool IsNull => Value == null;
}
 
struct Neko { }
Так же нужно не забывать, что вообще-то для структур будет происходит упаковка на этапе Value == null, т.к. всё будет приводится к object. А значит возможны такие приколы, когда значение внутри не меняется.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Neko neko = default;
var test = new Test<Neko>(neko);
var result1 = test.GetValueHashCode(); // 1
var result2 = neko.ToString(); // 0
 
class Test<T>(T item)
{
    public T Value { get; } = item;
    public string? GetValueString => Value?.ToString();
    public int? GetValueHashCode() => Value?.GetHashCode();
}
 
struct Neko
{
    public int x;
    public override string ToString() => $"{x}";
    public override int GetHashCode() => ++x;
}
1
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
14.11.2023, 23:07
Цитата Сообщение от PasterLak Посмотреть сообщение
Я делаю проект в Unity и класс Block наследуется от MonoBehaviour.
C этого и надо было начинать, а то привели код не полностью а мы тут гадаем...

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        public class Test
        {
            public static bool operator ==(Test a, Test b)
            {
                return true;
            }
 
            public static bool operator !=(Test a, Test b)
            {
                return false;
            }
        }
 
        public class TestData<T>
        {
            private T data;
 
            public TestData(T data)
            {
                this.data = data;
            }
 
            public bool IsDataNull()
            {
                return data == null;
            }
            public T GetData()
            {
                return data;
            }
        }
 
        class Block : Test { }
C#
1
2
3
4
5
6
            Block b = new Block();
            TestData<Block> test = new TestData<Block>(b);
 
            Console.WriteLine($"Is data null: {test.IsDataNull()}"); //  false
 
            Console.WriteLine($"Is GetData null: {(test.GetData() == null)}");  // true
Вот код который тоже выдает false/true...
1
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
14.11.2023, 23:24
Someone007, хм... я конечно знал что в Unity свой C#, но там реально такое поведение, что приходится перегружать операторы сравнения?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
18.11.2023, 21:19
Цитата Сообщение от PasterLak Посмотреть сообщение
== null возвращает неверное значение
Не стоит использовать типизированный оператор сравнение с null - в конкретном типе он может быть перегружен и возвращать совсем не то что вы ожидаете.

В современных версия Шарпа надо использовать data is null, в старых ReferenceEquals(data, null).

Добавлено через 2 минуты
Можно ещё использовать Equals(data, null) или ((object)data) == null. Но оба эти способа используют метод Equals, который тоже может быть переопределён - поэтому не советую.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.11.2023, 21:19
Помогаю со студенческими работами здесь

Получаю из метода неверное значение
Вообщем решал простенькую задачку и наткнулся на проблему public double GetVolume() =&gt;...

Функция возвращает неверное значение
Здравствуйте! Проверял одну функцию для своей другой программы и столкнулся с такой проблемой: функция возвращает неправильное значение....

Исправить метод, который возвращает неверное значение
Подскажите пожалуйста как переписать этот метод чтоб он возвращал переменную с (здесь не видно ее инициализации) public static int...

Рекордсет возвращает значение 'null'.
Рекордсет возвращает значение 'null'. Проверка типа if( rs.Fields('blab')==null) {....} - непроходит. Подскажите что здесь...

New возвращает Null
День добрый, подскажите почему new может возвращать Null есть многомерный массив в который пытаюсь проинициализировать созданием...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru