Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#if DEBUG for exception handling

Tags:

c#

I have a public method ChangeLanguage that is in a class library that is supposed to be used by other people who have no idea what the source code is but know what it can do.

public string ChangeLanguage(string language) 
{
    #if DEBUG
        // Check if the new language is not null or an empty string.
        language.ThrowArgumentNullExceptionIfNullOrEmpty("language", GetString("0x000000069"));
    #else
        if (string.IsNullOrEmpty(language))
            language = _fallbackLanguage;
    #endif 
}

For me it looked obvious to check if a language was actually passed to the method and if not, throw an error to the developer. Tho this is a very small performance loss, I think it's better to not throw an exception but just use the fallback language when no language was provided.

I'm wondering if this is a good design approach and if I should keep using it at other places in the library like here:

    _appResDicSource = Path.Combine("\\" + _projectName + ";component", _languagesDirectoryName, _fileBaseName + "_" + language + ".xaml");
    _clsLibResDicSource = "\\Noru.Base;component\\Languages\\Language_" + language + ".xaml";

    ResourceDictionary applicationResourceDictionary;
    ResourceDictionary classLibraryResourceDictionary;

    try { applicationResourceDictionary = new ResourceDictionary { Source = new Uri(_appResDicSource, UriKind.RelativeOrAbsolute) }; }
    catch
    {
#if DEBUG
        throw new IOException(string.Format(GetString("1x00000006A"), _appResDicSource));
#else
        return ChangeLanguage(_fallbackLanguage);
#endif
    }
    try { classLibraryResourceDictionary = new ResourceDictionary { Source = new Uri(_clsLibResDicSource, UriKind.RelativeOrAbsolute) }; }
    catch
    {
#if DEBUG
        throw new IOException(string.Format(GetString("1x00000006B"), _clsLibResDicSource));
#else
        return ChangeLanguage(_fallbackLanguage);
#endif
    }
like image 568
Krowi Avatar asked Dec 24 '22 20:12

Krowi


1 Answers

It depends on semantics of the call, but I would consider Debug.Fail (which will be eliminated if DEBUG is not defined):

public string ChangeLanguage(string language) 
{
    if (string.IsNullOrEmpty(language))
    {
        Debug.Fail("language is NOK");
        language = _fallbackLanguage;
    }
}

The issue is that, on the one hand, as mentioned by @OndrejTucny and @poke, it is not desirable to have different logic for different build configurations. It is correct.

But on the other hand, there are cases where you do not want the application to crash in the field due to a minor error. But if you just ignore the error unconditionally, you decrease the chances to detect it even on the local system.

I do not think that there is a universal solution. In general, you may end up deciding to throw or not, to log or not, to add an assertion or not, always or sometimes. And the answers depend on a concrete situation.

like image 114
AlexD Avatar answered Jan 13 '23 09:01

AlexD