Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.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# 空条件运算符到“0”;“无效”;数组元素存在性_C#_Arrays_Null_C# 6.0_Null Propagation Operator - Fatal编程技术网

C# 空条件运算符到“0”;“无效”;数组元素存在性

C# 空条件运算符到“0”;“无效”;数组元素存在性,c#,arrays,null,c#-6.0,null-propagation-operator,C#,Arrays,Null,C# 6.0,Null Propagation Operator,新的C#6.0空条件运算符是编写更简洁、更少复杂代码的便捷工具。假设有一个客户数组,那么如果customers为null,则可以使用以下示例获得null而不是长度: 类似地,您可以通过以下方式获得null,而不是客户: Customer first = customers?[0]; 对于更详细的表达式,如果客户为null,第一个客户为null,或者第一个客户的订单对象为null,则会产生null: int? count = customers?[0]?.Orders?.Count(); 但是

新的C#6.0空条件运算符是编写更简洁、更少复杂代码的便捷工具。假设有一个客户数组,那么如果
customers
为null,则可以使用以下示例获得null而不是长度:

类似地,您可以通过以下方式获得null,而不是客户:

Customer first = customers?[0];
对于更详细的表达式,如果
客户
为null,第一个客户为null,或者第一个客户的
订单
对象为null,则会产生null:

int? count = customers?[0]?.Orders?.Count();
但是还有一个有趣的例子,即不存在的客户,null条件运算符似乎没有解决这个问题。我们在上面看到,覆盖了空客户,即
customers
数组中的条目为空。但这与不存在的客户截然不同,例如,在3元素数组中查找客户
5
,或在0元素列表中查找客户
n
。(请注意,同样的讨论也适用于字典查找。)

在我看来,null条件运算符专门用于否定NullReferenceException的效果;IndexOutOfRangeException或KeyNotFoundException是单独的、暴露的、蜷缩在角落里的,需要自己照顾自己!我认为,本着空条件运算符的精神,它也应该能够处理这些情况。。。这就引出了我的问题

我错过了吗?空条件是否提供了任何优雅的方式来真正覆盖此表达式

customers?[0]?.Orders?.Count();

…当没有第零个元素时?

否,因为它是一个null-条件运算符,而不是一个indexootfrange-条件运算符,只是对以下内容的语法补充:

int? count = customers?[0]?.Orders?.Count();

if (customers != null && customers[0] != null && customers[0].Orders != null)
{
    int count = customers[0].Orders.Count();
}
您可以看到,如果没有第0个客户,您将获得常规的
索引autofrangeexception

解决此问题的一种方法是使用一个扩展方法来检查索引,如果索引不存在,则返回null:

public static Customer? GetCustomer(this List<Customer> customers, int index)
{
    return customers.ElementAtOrDefault(index); // using System.Linq
}

它不支持索引的安全性,因为当你认真研究它时,索引器实际上只是任何其他类型方法的语法糖

例如:

public class MyBadArray
{
    public Customer this[int a]
    {
        get
        {
            throw new OutOfMemoryException();
        }
    }
}

var customers = new MyBadArray(); 
int? count = customers?[5]?.Orders?.Count();
void Main()
{
    var thing = new MyBadThing(); 
    thing.GetBoss()?.FireSomeone();
}

public class MyBadThing
{
    public class Boss
    {
        public void FireSomeone() 
        { 
            throw new NullReferenceException();
        }
    }
    public Boss GetBoss()
    {
        return new Boss();
    }
}
这个应该在这里抓到吗?如果异常更合理,类似于KeyNotFoundException,但特定于我们正在实现的集合类型,该怎么办?我们必须不断更新
?。
功能才能跟上进度

此外,
?。
不会捕获异常。它阻止了他们

var客户=客户?[5]实际上编译为:

Customer customer = null;
if (customers != null)
    customer = customers[5];
让它捕获异常变得异常困难。例如:

public class MyBadArray
{
    public Customer this[int a]
    {
        get
        {
            throw new OutOfMemoryException();
        }
    }
}

var customers = new MyBadArray(); 
int? count = customers?[5]?.Orders?.Count();
void Main()
{
    var thing = new MyBadThing(); 
    thing.GetBoss()?.FireSomeone();
}

public class MyBadThing
{
    public class Boss
    {
        public void FireSomeone() 
        { 
            throw new NullReferenceException();
        }
    }
    public Boss GetBoss()
    {
        return new Boss();
    }
}
如果它只是捕获异常,那么它将被写为:

Boss boss = customer.GetBoss();
try 
{
    boss.FireSomeone();
} catch (NullReferenceException ex) { 

}
这将实际捕获
FireSomeone
中的异常,而不是在boss为null时抛出的null引用异常

如果我们捕获索引查找异常、未找到键异常等,同样的错误捕获问题也会出现

customers?.FirstOrDefault()?.Orders?.Count();

没有零,就没有问题。

如果要获取第n个元素而不存在NullReference或IndexOutfrange异常,可以使用:


“空条件运算符”,而不是“异常全局运算符”。就个人而言,我会考虑不直观的行为,如果它绕过OutoCopyExxExtExcuts/KeNoTuffExtExpCultUnLules。<代码> ./COD>运算符只需将代码封装在<代码>中(如果(Val.!= null){…//继续} /代码>。code>IndexOutOfRangeException
可以来自任何地方,许多类确实会抛出它。就传统数组而言,索引操作也不一定意味着索引查找,它还用于字典/查找等。捕捉这种异常是没有意义的。不要害怕零。您找到了一种解决方案,可以将[0]替换为“FirstOrDefault”,但问题更为一般,关于[index],其中索引可能超出数组边界..实际上我在
Dictionary
上使用了一个名为
ElementAtOrNull
的扩展方法,它通过返回
Dictionary.ContainsKey(lookupValue)以类似的方式运行?dictionary[lookupValue]:null
最好将ElementAtOrDefault信息移到更靠近答案顶部的位置。它看起来像是一个标准函数,并且完全满足用户的需求。带有In吞ArgumentOutRange异常的重写运算符[]应该可以工作。这是迄今为止最优雅的解决方案
customers?.Skip(n)?.FirstOrDefault()