我喜欢null-coalescing运算符,因为它可以很容易地为可空类型分配默认值。
int y = x ?? -1;
这很好,除非我需要用x
做一些简单的事情。例如,如果我想检查Session
,那么我通常最终必须写一些更冗长的内容。
我希望我能做到这一点:
string y = Session["key"].ToString() ?? "none";
但是你不能因为.ToString()
在空检查之前被调用所以如果Session["key"]
为空则失败。我最终这样做了:
string y = Session["key"] == null ? "none" : Session["key"].ToString();
在我看来,它比三线替代方案更有效,更好:
string y = "none";
if (Session["key"] != null)
y = Session["key"].ToString();
尽管有效,但如果有更好的方法,我仍然很好奇。似乎无论我总是要两次引用Session["key"]
;一次检查,再次检查。有什么想法吗?
答案 0 :(得分:183)
怎么样?
string y = (Session["key"] ?? "none").ToString();
答案 1 :(得分:130)
如果您经常使用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");
答案 2 :(得分:21)
答案 3 :(得分:14)
如果它始终是string
,您可以施放:
string y = (string)Session["key"] ?? "none";
如果某人在int
中填写了Session["key"]
或其他内容,则此优势就是抱怨而不是隐藏错误。 ;)
答案 4 :(得分:10)
所有建议的解决方案都很好,并回答问题;所以这只是略微延伸。目前,大多数答案仅处理空验证和字符串类型。您可以扩展StateBag
对象以包含通用GetValueOrDefault
方法,类似于Jon 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;
}
答案 5 :(得分:7)
我们使用名为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();
}
}
答案 6 :(得分:6)
我的偏好,对于一次性,将使用安全强制转换为字符串,以防与密钥存储的对象不是一个。使用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;
答案 7 :(得分:3)
创建辅助功能
public static String GetValue( string key, string default )
{
if ( Session[ key ] == null ) { return default; }
return Session[ key ].toString();
}
string y = GetValue( 'key', 'none' );
答案 8 :(得分:2)
Skeet的答案是最好的 - 特别是我觉得他的ToStringOrNull()
非常优雅,最适合你的需要。我想在扩展方法列表中再添加一个选项:
// Method:
public static object OrNullAsString(this object input, string defaultValue)
{
if (defaultValue == null)
throw new ArgumentNullException("defaultValue");
return input == null ? defaultValue : input;
}
// Example:
var y = Session["key"].OrNullAsString("defaultValue");
使用var
作为返回值,因为它将作为原始输入的类型返回,仅作为null
答案 9 :(得分:0)
对于不支持的.NET版本,这是我的小型安全“Elvis运算符”。
public class IsNull
{
public static O Substitute<I,O>(I obj, Func<I,O> fn, O nullValue=default(O))
{
if (obj == null)
return nullValue;
else
return fn(obj);
}
}
第一个参数是测试对象。第二是功能。第三个是空值。所以对于你的情况:
IsNull.Substitute(Session["key"],s=>s.ToString(),"none");
对于可空类型也非常有用。例如:
decimal? v;
...
IsNull.Substitute(v,v.Value,0);
....