![](/img/trans.png)
[英]How do I specify "any non-nullable type" as a generic type parameter constraint?
[英]How do I specify a constraint that says “collection of nullable types”?
我正在嘗試創建一個通用的參數驗證方法,該方法檢查集合參數是否為null,empty或包含null元素 。
public void Foo(ICollection<MyType> bar)
{
// Validate parameters
ThrowIfNullEmptyOrContainsNull(bar, "bar");
.
.
.
如果我僅在類型約束中指定ICollection<T>
,則if (value.Contains(null))
生成錯誤,因為T
可能不是可為空的類型。
這是我想出的,但似乎並不正確:
internal static T1 ThrowIfNullEmptyOrContainsNull<T1, T2>(T1 value, string name)
where T1 : ICollection<T2>
where T2 : class
{
if (ReferenceEquals(value, null))
throw new ArgumentNullException(name);
if (value.Count == 0)
throw new ArgumentException("Empty collection not allowed", name);
if (value.Contains(null))
throw new ArgumentException("Collection contains one or more null elements", name);
return value;
}
...但是然后我必須使用顯式參數類型調用該方法,如下所示:
public void Foo(ICollection<MyType> bar)
{
// Validate parameters
ThrowIfNullEmptyOrContainsNull<(ICollection<MyType>, MyType>(bar, "bar");
.
.
.
如果沒有在調用中明確指定T1和T2,則會出現錯誤“無法從用法中推斷出類型實參...”。
誰能闡明該怎么做?
只是不要使用Contains
。 遍歷集合並將值顯式比較為null
:
internal static T1 ThrowIfNullEmptyOrContainsNull<T1, T2>(T1 value, string name)
where T1 : ICollection<T2>
{
if (ReferenceEquals(value, null))
throw new ArgumentNullException(name);
if (value.Count == 0)
throw new ArgumentException("Empty collection not allowed", name);
foreach (var item in value)
if (item == null)
throw new ArgumentException("Collection contains one or more null elements", name);
return value;
}
怎么樣呢?
if (value.Any(item => item == null))
{
throw new ArgumentException("Collection contains one or more null elements", name);
}
如:
internal static T1 ThrowIfNullEmptyOrContainsNull<T1, T2>(T1 value, string name)
where T1 : ICollection<T2>
{
if (ReferenceEquals(value, null))
throw new ArgumentNullException(name);
if (value.Count == 0)
throw new ArgumentException("Empty collection not allowed", name);
if (value.Any(item => item == null))
throw new ArgumentException("Collection contains 1 or more null items", name);
return value;
}
擴展方法呢? 根據需要包裝異常或消息
public static bool IsNullOrEmpty<T>(this ICollection<T> alist) where T:class
{
if (alist == null || alist.Count == 0){
return true;
}
if (alist.Any(t => t == null)) {
return true;
}
return false;
}
采用:
if ( myList.IsNullOrEmpty ) {
//.. exception, error handling
}
無需傳遞MyList的類型,因為MyList必須實現ICollection可能對您有用,無需傳遞類型要求。
在建議中添加了T:Class。 但是您已經知道了:-)
我們可以將非空類型與null進行比較,因為所有對象都可以轉換為object
,因此可以進行比較:
bool obviouslyFalse = 1 == null;
這將導致警告,但有效。 顯然,它總是false
,實際上編譯器將通過刪除比較並給我們等效項來進行優化,就好像我們有bool obviouslyFalse = false;
。
對於泛型,適用於以下情況:
T item = getTFromSomewhere;
bool obviouslyFalseIfTIsntNullable = item == null;
然后,這對於所有可能的T
有效,並且盡管編譯器無法刪除比較,但抖動確實可以並且確實可以。
因此,我們可以擁有:
internal static TCol ThrowIfNullEmptyOrContainsNull<TCol, TEl>(TCol collection, string name)
where TCol : ICollection<TEl>
{
if (ReferenceEquals(value, null))
throw new ArgumentNullException(name);
if (value.Count == 0)
throw new ArgumentException("Empty collection not allowed", name);
foreach(var item in collection)
if(item == null)
throw new ArgumentException("Collection cannot contain null elements", name);
return value;
}
這會起作用,但是如果我們有大量非空類型的集合,那將會很浪費。 即使不執行任何操作,抖動也不可能刪除該迭代,因此它仍將獲得一個枚舉數並對其調用MoveNext()
,直到返回false。 我們可以幫助您:
internal static TCol ThrowIfNullEmptyOrContainsNull<TCol, TEl>(TCol collection, string name)
where TCol : ICollection<TEl>
{
if (ReferenceEquals(value, null))
throw new ArgumentNullException(name);
if (value.Count == 0)
throw new ArgumentException("Empty collection not allowed", name);
if(default(TEl) == null)
foreach(var item in collection)
if(item == null)
throw new ArgumentException("Collection cannot contain null elements", name);
return value;
}
因為default(TEl) == null
對於可為null的類型(包括Nullable<T>
)始終為true,對於非可為null的類型始終為false,因此通過消除所有類型的比較並為非null的類型刪除整個枚舉,將優化抖動-可空類型。 因此,該方法將可以立即處理大量的整數數組(例如)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.