[C#] null 값을 확인하는 적절한 방법은 무엇입니까?

nullable 형식에 대한 기본값을 쉽게 할당 할 수 있기 때문에 null 통합 연산자를 좋아합니다.

 int y = x ?? -1;

.NET으로 간단한 작업을 수행해야하는 경우를 제외하고는 훌륭 x합니다. 예를 들어을 확인하려면 Session일반적으로 더 자세한 내용을 작성해야합니다.

나는 이것을 할 수 있기를 바랍니다.

string y = Session["key"].ToString() ?? "none";

그러나 .ToString()null 검사 전에 호출되므로 null이면 실패합니다 Session["key"]. 나는 이것을 끝낸다 :

string y = Session["key"] == null ? "none" : Session["key"].ToString();

제 생각에는 3 줄 대안보다 작동하고 더 좋습니다.

string y = "none";
if (Session["key"] != null)
    y = Session["key"].ToString();

작동하지만 더 나은 방법이 있는지 여전히 궁금합니다. 내가 항상 Session["key"]두 번 언급해야하는 것이 무엇이든 상관없는 것 같습니다 . 확인을 위해 한 번, 할당을 위해 다시. 어떤 아이디어?



답변

이건 어떤가요

string y = (Session["key"] ?? "none").ToString();


답변

자주 이런 일을하는 경우 특별히ToString() 당신은 확장 메서드를 작성할 수 :

public static string NullPreservingToString(this object input)
{
    return input == null ? null : input.ToString();
}

...

string y = Session["key"].NullPreservingToString() ?? "none";

또는 물론 기본값을 사용하는 방법 :

public static string ToStringOrDefault(this object input, string defaultValue)
{
    return input == null ? defaultValue : input.ToString();
}

...

string y = Session["key"].ToStringOrDefault("none");


답변

를 사용할 수도 있습니다 . 변환이 실패하면 다음 as과 같이 산출 null됩니다.

Session["key"] as string ?? "none"

이것은 반환 "none"누군가가 박제 경우에도 int의를 Session["key"].


답변

항상 string이면 다음을 전송할 수 있습니다.

string y = (string)Session["key"] ?? "none";

이것은 누군가가 .NET에서 int무언가를 채우면 실수를 숨기는 대신 불평하는 장점이 있습니다 Session["key"]. 😉


답변

제안 된 모든 솔루션이 훌륭하며 질문에 답하십시오. 그래서 이것은 약간 확장하는 것입니다. 현재 대부분의 답변은 null 유효성 검사 및 문자열 유형 만 처리합니다. StateBag객체를 확장하여 일반GetValueOrDefaultJon Skeet이 게시 한 답변과 유사한 메서드 .

문자열을 키로 받아들이고 유형을 확인하는 간단한 일반 확장 메서드는 세션 개체를 확인합니다. 개체가 null이거나 유형이 같지 않으면 기본값이 반환되고, 그렇지 않으면 세션 값이 강력한 형식으로 반환됩니다.

이 같은

/// <summary>
/// Gets a value from the current session, if the type is correct and present
/// </summary>
/// <param name="key">The session key</param>
/// <param name="defaultValue">The default value</param>
/// <returns>Returns a strongly typed session object, or default value</returns>
public static T GetValueOrDefault<T>(this HttpSessionState source, string key, T defaultValue)
{
    // check if the session object exists, and is of the correct type
    object value = source[key]
    if (value == null || !(value is T))
    {
        return defaultValue;
    }

    // return the session object
    return (T)value;
}


답변

우리는 NullOr .

용법

// Call ToString() if it’s not null, otherwise return null
var str = myObj.NullOr(obj => obj.ToString());

// Supply default value for when it’s null
var str = myObj.NullOr(obj => obj.ToString()) ?? "none";

// Works with nullable return values, too —
// this is properly typed as “int?” (nullable int)
// even if “Count” is just int
var count = myCollection.NullOr(coll => coll.Count);

// Works with nullable input types, too
int? unsure = 47;
var sure = unsure.NullOr(i => i.ToString());

출처

/// <summary>Provides a function delegate that accepts only value types as return types.</summary>
/// <remarks>This type was introduced to make <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncStruct{TInput,TResult})"/>
/// work without clashing with <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncClass{TInput,TResult})"/>.</remarks>
public delegate TResult FuncStruct<in TInput, TResult>(TInput input) where TResult : struct;

/// <summary>Provides a function delegate that accepts only reference types as return types.</summary>
/// <remarks>This type was introduced to make <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncClass{TInput,TResult})"/>
/// work without clashing with <see cref="ObjectExtensions.NullOr{TInput,TResult}(TInput,FuncStruct{TInput,TResult})"/>.</remarks>
public delegate TResult FuncClass<in TInput, TResult>(TInput input) where TResult : class;

/// <summary>Provides extension methods that apply to all types.</summary>
public static class ObjectExtensions
{
    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult NullOr<TInput, TResult>(this TInput input, FuncClass<TInput, TResult> lambda) where TResult : class
    {
        return input == null ? null : lambda(input);
    }

    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult? NullOr<TInput, TResult>(this TInput input, Func<TInput, TResult?> lambda) where TResult : struct
    {
        return input == null ? null : lambda(input);
    }

    /// <summary>Returns null if the input is null, otherwise the result of the specified lambda when applied to the input.</summary>
    /// <typeparam name="TInput">Type of the input value.</typeparam>
    /// <typeparam name="TResult">Type of the result from the lambda.</typeparam>
    /// <param name="input">Input value to check for null.</param>
    /// <param name="lambda">Function to apply the input value to if it is not null.</param>
    public static TResult? NullOr<TInput, TResult>(this TInput input, FuncStruct<TInput, TResult> lambda) where TResult : struct
    {
        return input == null ? null : lambda(input).Nullable();
    }
}


답변

일회성에 대한 나의 선호는 키와 함께 저장된 객체가 하나가 아닌 경우 문자열에 대한 안전한 캐스트를 사용하는 것입니다. 사용 ToString()하면 원하는 결과가 없을 수 있습니다.

var y = Session["key"] as string ?? "none";

@Jon Skeet이 말했듯이,이 작업을 많이 수행하는 경우 확장 메서드 또는 더 나은 방법이지만 강력한 형식의 SessionWrapper 클래스와 함께 확장 메서드를 사용할 수 있습니다. 확장 메서드가 없어도 강력한 형식의 래퍼가 좋은 생각 일 수 있습니다.

public class SessionWrapper
{
    private HttpSessionBase Session { get; set; }

    public SessionWrapper( HttpSessionBase session )
    {
        Session = session;
    }

    public SessionWrapper() : this( HttpContext.Current.Session ) { }

    public string Key
    {
         get { return Session["key"] as string ?? "none";
    }

    public int MaxAllowed
    {
         get { return Session["maxAllowed"] as int? ?? 10 }
    }
}

사용

 var session = new SessionWrapper(Session);

 string key = session.Key;
 int maxAllowed = session.maxAllowed;