Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何指定一个表示为“的约束?”;可为空类型的集合";?_C#_.net_Nullable_Generic Collections_Type Constraints - Fatal编程技术网

C# 我如何指定一个表示为“的约束?”;可为空类型的集合";?

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"); . . . …但我必须使用显式参数类型调用该

我正在尝试创建一个通用参数验证方法,用于检查集合参数是否为null、empty或包含null元素

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;
}