C# 我如何指定一个表示为“的约束?”;可为空类型的集合";?
我正在尝试创建一个通用参数验证方法,用于检查集合参数是否为null、empty或包含null元素C# 我如何指定一个表示为“的约束?”;可为空类型的集合";?,c#,.net,nullable,generic-collections,type-constraints,C#,.net,Nullable,Generic Collections,Type Constraints,我正在尝试创建一个通用参数验证方法,用于检查集合参数是否为null、empty或包含null元素 public void Foo(ICollection<MyType> bar) { // Validate parameters ThrowIfNullEmptyOrContainsNull(bar, "bar"); . . . …但我必须使用显式参数类型调用该
public void Foo(ICollection<MyType> bar)
{
// Validate parameters
ThrowIfNullEmptyOrContainsNull(bar, "bar");
.
.
.
…但我必须使用显式参数类型调用该方法,如下所示:
public void Foo(ICollection<MyType> bar)
{
// Validate parameters
ThrowIfNullEmptyOrContainsNull<(ICollection<MyType>, MyType>(bar, "bar");
.
.
.
public void Foo(i收集栏)
{
//验证参数
ThrowifNullEmptyorContainesnull(酒吧,简称“酒吧”);
.
.
.
如果没有在调用中显式指定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;
}
内部静态T1 throwifnullemptyorcainsnall(T1值,字符串名称)
其中T1:i收集
{
if(ReferenceEquals(value,null))
抛出新的ArgumentNullException(名称);
如果(value.Count==0)
抛出新ArgumentException(“不允许空集合”,名称);
foreach(价值中的var项目)
如果(项==null)
抛出新ArgumentException(“集合包含一个或多个null元素”,name);
返回值;
}
像这样的东西怎么样:
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;
}
内部静态T1 throwifnullemptyorcainsnall(T1值,字符串名称)
其中T1:i收集
{
if(ReferenceEquals(value,null))
抛出新的ArgumentNullException(名称);
如果(value.Count==0)
抛出新ArgumentException(“不允许空集合”,名称);
if(value.Any(item=>item==null))
抛出新ArgumentException(“集合包含1个或多个null项”,名称);
返回值;
}
扩展方法如何。根据需要使用异常或消息进行包装
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;
}
无需传递MyList的类型,因为MyList必须实现ICollection
可能对您有用,无需通过类型要求。将T:Class添加到建议中。但您已经知道:-)我们可以将不可为null的类型与null进行比较,因为所有对象都可以强制转换为
对象,因此可以进行比较:
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;
}
因为对于可为null的类型(包括可为null的
),默认值(TEl)=null始终为true,对于不可为null的类型,默认值始终为false,抖动将通过删除所有类型的此比较,并删除不可为null的类型的整个枚举来优化。因此,大量整数数组(例如)将立即被该方法批准。我无法将您问题的标题与正文相协调-您能尝试稍微澄清一下任务/问题吗?@usr不,他确实需要T1。如果他没有T1,那么他将在调用该方法时低估返回的值。两种可能的不同方法不能完全回答您的问题埃德:如果你的集合都实现了非泛型的ICollection
,你可以改用它,忘记约束。它不会抱怨任何ICollection
包含null
,这似乎没问题,因为它永远不会。除此之外,你可以重载你的方法,这样你就有了一个方法对于引用类型,一个不同的方法(使用相同的名称)用于可空值类型。我编辑了我的问题以使其更清晰。基本上,我试图确保仅为ICollection(而不是类似ICollection的东西)调用此方法。类型约束语法让我感到困惑。最初,我只是使用了where T:ICollection
,但它允许像int
@ScottSmith这样的不可为null的类型。没有说“T
必须为null”的泛型参数约束其中T:class
意味着T
必须是引用类型,这不允许使用可为null的值类型,例如int?
。接受引用类型的唯一方法是,也接受可为null的值类型,但不接受不可为null的值类型,将前两种类型分开,为它们提供不同的重载我会得到一个编译错误,因为value
是类型为T
的对象集合,所以item
可能不是可为null的类型。没错,我没有得到编译错误,但我得到一个警告:“值类型可能与'null'比较”。问题是,我试图限制传入参数,使其不允许传入值类型的集合。嗯,我可以这样做吗?公共静态bool IsNullOrEmpty(此ICollection列表),其中t:class{
?int?
是可为空的类型,但将被类
阻止。
T item = getTFromSomewhere;
bool obviouslyFalseIfTIsntNullable = item == null;
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;
}
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;
}