Repository: microsoft/terminal
File: src/cascadia/TerminalSettingsEditor/Appearances.cpp (C++)

Code before:
        _NotifyChanges(L"FontAxes");
        _NotifyChanges(L"FontFeatures");
        _NotifyChanges(L"HasFontAxes");
        _NotifyChanges(L"HasFontFeatures");
    }

    // Call this when used items moved into unused and vice versa.
    // Because this doesn't recreate the IObservableVector instances,
    // we don't need to notify the UI about changes to the "FontAxes" property.
    void AppearanceViewModel::_notifyChangesForFontSettingsReactive(FontSettingIndex fontSettingsIndex)
    {
        _NotifyChanges(L"FontFaceDependents");
        switch (fontSettingsIndex)
        {
        case FontAxesIndex:
            _NotifyChanges(L"HasFontAxes");
            break;
        case FontFeaturesIndex:
            _NotifyChanges(L"HasFontFeatures");
            break;
        default:
            break;
        }
    }

    double AppearanceViewModel::_extractCellSizeValue(const hstring val) const
    {
        const auto str = val.c_str();

        auto& errnoRef = errno; // Nonzero cost, pay it once.
        errnoRef = 0;

        wchar_t* end;
        const auto value = std::wcstod(str, &end);

        return str == end || errnoRef == ERANGE ? NAN : value;
    }

    double AppearanceViewModel::LineHeight() const
    {
        const auto cellHeight = _appearance.SourceProfile().FontInfo().CellHeight();
        return _extractCellSizeValue(cellHeight);
    }

    double AppearanceViewModel::CellWidth() const
    {
        const auto cellWidth = _appearance.SourceProfile().FontInfo().CellHeight();
        return _extractCellSizeValue(cellWidth);
    }

#define CELL_SIZE_SETTER(modelName, viewModelName)                 \

Review comment (refactor):
```suggestion
    double AppearanceViewModel::_extractCellSizeValue(const hstring& val) const
```

technically best practice

Code after:
        _NotifyChanges(L"FontAxes");
        _NotifyChanges(L"FontFeatures");
        _NotifyChanges(L"HasFontAxes");
        _NotifyChanges(L"HasFontFeatures");
    }

    // Call this when used items moved into unused and vice versa.
    // Because this doesn't recreate the IObservableVector instances,
    // we don't need to notify the UI about changes to the "FontAxes" property.
    void AppearanceViewModel::_notifyChangesForFontSettingsReactive(FontSettingIndex fontSettingsIndex)
    {
        _NotifyChanges(L"FontFaceDependents");
        switch (fontSettingsIndex)
        {
        case FontAxesIndex:
            _NotifyChanges(L"HasFontAxes");
            break;
        case FontFeaturesIndex:
            _NotifyChanges(L"HasFontFeatures");
            break;
        default:
            break;
        }
    }

    double AppearanceViewModel::_parseCellSizeValue(const hstring& val) const
    {
        const auto str = val.c_str();

        auto& errnoRef = errno; // Nonzero cost, pay it once.
        errnoRef = 0;

        wchar_t* end;
        const auto value = std::wcstod(str, &end);

        return str == end || errnoRef == ERANGE ? NAN : value;
    }

    double AppearanceViewModel::LineHeight() const
    {
        const auto cellHeight = _appearance.SourceProfile().FontInfo().CellHeight();
        return _parseCellSizeValue(cellHeight);
    }

    double AppearanceViewModel::CellWidth() const
    {
        const auto cellWidth = _appearance.SourceProfile().FontInfo().CellWidth();
        return _parseCellSizeValue(cellWidth);
    }

#define CELL_SIZE_SETTER(modelName, viewModelName)                 \