Альтернативы nullable типам в C#

Если вы хотите удалить виджет из макета, вам просто нужно использовать deleteLater, но это не значит, что ссылки будут удалены, если они будут сохранены в списке. В моей стратегии я удаляю все QLineEdits с помощью deleteLater, я сбрасываю список, в котором он хранится, и создаю новые QLineEdits.

from PySide2 import QtCore, QtWidgets

class RollMultiDiePopup(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(RollMultiDiePopup, self).__init__(parent)

        self._data = {
            "D4": 4, 
            "D6": 6, 
            "D8": 8, 
            "D10": 10, 
            "D12": 12, 
            "D20": 20
        }

        self._lineedits = [[] for _ in self._data]
        self._comboboxes = []

        grid_layout = QtWidgets.QGridLayout(self)
        self.create_labels()
        self.create_comboboxes()
        self.create_buttons()

    def create_labels(self):
        row = 0
        grid_layout = self.layout()
        for i, k in enumerate(self._data.keys()):
            label = QtWidgets.QLabel("# of {}s".format(k))
            grid_layout.addWidget(label, row, i)

    def create_comboboxes(self):
        row = 1
        grid_layout = self.layout()
        for i in range(len(self._data)):
            combo = QtWidgets.QComboBox()
            combo.addItems([str(j) for j in range(21)])
            self._comboboxes.append(combo)
            grid_layout.addWidget(combo, row, i)

    def create_buttons(self):
        row = 2
        grid_layout = self.layout()
        for i, (k, v) in enumerate(self._data.items()):
            button = QtWidgets.QPushButton("Roll {}s".format(k))
            button.setToolTip("Roll {}(1 - {})".format(k, v))
            button.clicked.connect(self.update_lineedits)
            grid_layout.addWidget(button, row, i)

    @QtCore.Slot()
    def update_lineedits(self):
        row = 3
        grid_layout = self.layout()
        for r in self._lineedits:
            for le in r:
                le.deleteLater()
        self._lineedits = [[] for _ in self._data]
        for i, (les,combo) in enumerate(zip(self._lineedits, self._comboboxes)):
            v = int(combo.currentText())
            for j in range(v):
                le = QtWidgets.QLineEdit()
                le.setPlaceholderText("Die Roll #{}".format(j+1))
                grid_layout.addWidget(le, row+j, i)
                les.append(le)
        QtCore.QTimer.singleShot(0, self.adjust_size)

    @QtCore.Slot()
    def adjust_size(self):
        animation = QtCore.QPropertyAnimation(self, b"size", self)
        animation.setStartValue(self.size())
        animation.setEndValue(self.minimumSizeHint())
        animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = RollMultiDiePopup()
    w.show()
    sys.exit(app.exec_())
12
задан Ryan 18 May 2009 в 09:49
поделиться

5 ответов

Что ж, если вы исключили Nullable , у вас останутся значения домена - то есть магическое число, которое вы считаете нулевым. Хотя это не идеальный вариант , это тоже не редкость - например, большая часть кода основного фреймворка трактует DateTime.MinValue так же, как null. Это, по крайней мере, уводит ущерб далеко от обычных значений ...

отредактируйте, чтобы выделить только там, где нет NaN

Итак, где нет NaN , возможно, используйте . MinValue - но просто помните, какие беды случаются, если вы случайно используете то же значение, означающее то же число ...

Очевидно, для данных без знака вам понадобится .MaxValue (избегайте нуля !!!).

Лично я бы попытался использовать Nullable для более безопасного выражения моих намерений ... могут быть способы оптимизировать ваш Nullable < T> код, пожалуй. А также - к тому времени, когда вы проверите магическое число во всех необходимых вам местах, возможно, оно будет не намного быстрее, чем Nullable ?

возможно, есть способы оптимизировать ваш код Nullable . А также - к тому времени, когда вы проверите магическое число во всех необходимых вам местах, возможно, оно будет не намного быстрее, чем Nullable ?

возможно, есть способы оптимизировать ваш код Nullable . А также - к тому времени, когда вы проверите магическое число во всех необходимых вам местах, возможно, оно будет не намного быстрее, чем Nullable ?

18
ответ дан 2 December 2019 в 05:28
поделиться

Я несколько не согласен с Gravell в этом конкретном пограничном случае: переменная с нулевым значением считается «не определенной», у нее нет значения. Так что все, что используется для обозначения того, что это нормально: даже магические числа, но с магическими числами вы должны учитывать, что магическое число всегда будет преследовать вас в будущем, когда оно внезапно станет «действительным» значением. С Double.NaN вам не нужно этого бояться: он никогда не станет действительным дублем. Хотя вы должны учитывать, что NaN в смысле последовательности двойников может использоваться только как маркер для «не определено», очевидно, вы также не можете использовать его в качестве кода ошибки в последовательностях.

Итак, что бы ни использовалось для обозначения «неопределенного»: в контексте набора значений должно быть ясно, что это конкретное значение считается значением для 'undefined' И которое не изменится в будущем.

Если Nullable доставляет вам слишком много хлопот, используйте NaN или что-то еще, если вы учитываете последствия: выбранное значение представляет «undefined», и оно останется.

4
ответ дан 2 December 2019 в 05:28
поделиться

Я работаю над большим проектом, в котором NaN используется в качестве нулевого значения. Мне это не совсем комфортно - по тем же причинам, что и ваша: я не знаю, что может пойти не так. Пока мы не сталкивались с какими-либо реальными проблемами, но имейте в виду следующее:

NaN арифметика - Хотя в большинстве случаев «NaN-продвижение» - это хорошо, это может не всегда быть тем, что вы ожидайте.

Сравнение - Сравнение значений становится довольно дорогим, если вы хотите, чтобы NaN сравнивались равными. В любом случае, проверка чисел с плавающей запятой на равенство непроста, но упорядочивание (a

Заражение кода - Я вижу много арифметического кода, который требует правильной обработки NaN. Таким образом, вы получаете «функции, которые принимают NaN» и «функции, которые не принимают» по соображениям производительности.

Другие нефинитные NaN не является единственным не конечным значением. Следует иметь в виду ...

Исключения с плавающей точкой не являются проблемой, когда они отключены. Пока кто-то их не разрешит. Реальная история: статическая инициализация NaN в элементе управления ActiveX. Звучит не страшно, пока вы не измените установку на использование InnoSetup, в котором используется ядро ​​Pascal / Delphi (?), В котором по умолчанию включены исключения FPU. Мне потребовалось время, чтобы понять.

Так что, в общем, ничего серьезного, хотя я бы предпочел не рассматривать NaN так часто.


Я бы использовал типы, допускающие значение NULL, как можно чаще, если только они не являются (доказанными) ограничениями производительности / ресурсов. В одном случае могут быть большие векторы / матрицы со случайными NaN или большие наборы именованных отдельных значений , где поведение NaN по умолчанию является правильным .


В качестве альтернативы вы можете использовать вектор индекса для векторов и матриц, стандартный реализации с «разреженной матрицей» или отдельный логический / битовый вектор.

4
ответ дан 2 December 2019 в 05:28
поделиться

Возможно, значительное снижение производительности произойдет при вызове одного из членов или свойств Nullable (упаковка).

Попробуйте использовать структуру с двойным + логическим значением, указывающим, указано ли значение или нет.

0
ответ дан 2 December 2019 в 05:28
поделиться

Частичный ответ:

Float и Double обеспечивают NaN (не число). NaN немного сложнее, поскольку, согласно спецификации, NaN! = NaN. Если вы хотите узнать, является ли число NaN, вам нужно использовать Double.IsNaN ().

См. Также Двоичная с плавающей запятой и .NET .

2
ответ дан 2 December 2019 в 05:28
поделиться
Другие вопросы по тегам:

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