当子对象为空时访问另一个对象中包含的对象中的变量

时间:2015-05-14 08:18:10

标签: c#

我有以下两个班级。地址包含地址列表。方法GetMailingAddress将扫描AddressList以查找特定类型的地址。

Class Addresses
{
   public List<Address> AddressList {get; set;}

   public Address MailingAddress {get { return GetMailingAddress();}
}

Class Address
{
   public Int? ID {get; set;}
}

要访问MailingAddress的ID,我将输入以下内容:

Addresses obj = new Addresses();
int? I = obj.MailingAddress.ID

问题是MailingAddress可以返回null。如果发生这种情况,则调用失败,因为它通过null对象引用ID。在这种情况下,我想返回null。

要解决此问题,请使用以下代码:

if(obj.MailingAddress == null)
{
    I? = null;
}
else
{
    I? = obj.MailingAddress.ID;
}

有没有办法调用obj.MailingAddress.ID并且如果MailingAddress为null则返回null,而不必执行上述If语句。

我还可以像这样在类地址中创建一个额外的方法/属性,但我再次将其视为一种解决方法,而不是一个干净的解决方案:

public int? MailingAddressID
{
    if(GetMailingAddress == null)
    {
        return null;
    }
    else
    {
        return GetMailingAddress.ID;
    }
}

2 个答案:

答案 0 :(得分:2)

首先int是结构,你必须使用?Nullable<int>使其可以为空,然后:

int? myInt = obj.MailingAddress == null ? (int?)null : (int?)obj.MailingAddress.Id;

但是,在C#6中,您可以使用?运算符,有时也称为 Safe Navigation Operator

int? myInt = obj?.MailingAddress?.Id;

作为补充说明,您可以使用Null Object Pattern。您可以从here了解它并使用此模式。 Null Object模式的使用简化了代码,使其不易出错。

答案 1 :(得分:0)

这是C#5中C#6 Null Propagation语法的愚蠢实现:

using System;
using System.Diagnostics;

public class Program
{
    public static void Main()
    {
        var foo = new Foo { Bar = new Bar { Baz = "Hello" } };
        var foo1 = new Foo();

        var i = foo._(_=>_.Bar)._(_=>_.Baz);            //equivalent to foo?.Bar?.Baz in C# 6       
        Console.WriteLine("i is '{0}'", i);             //should be 'Hello'

        var j = foo1._(_=>_.Bar)._(_=>_.Baz);           //equivalent to foo1?.Bar?.Baz in C# 6      
        Console.WriteLine("j is '{0}'",j);              //should be '' since j is null, but shouldn't throw exception either.

        Console.WriteLine("js is null? {0}", j == null);

    }
}

public class Foo 
{
    public Bar Bar { get; set; }
}

public class Bar
{
    public string Baz { get; set; }
}

public static class ObjectExtension
{
    //Probably not a good idea to name your method _, but it's the shortest one I can find, I wish it could be _?, but can't :(
    public static K _<T, K>(this T o, Func<T, K> f) 
    {
        try 
        {
            var z = f(o);
            return z;           
        }
        catch(NullReferenceException nex) 
        {
            Trace.TraceError(nex.ToString());
            return default(K);
        }

    }
}

基本上我想做foo?.Bar?.Baz,但由于语法不受支持,扩展方法Func<..>和救援的通用......

这样您就不需要将对象更改为可空版本,但需要在调用扩展方法_中指定其类型。 foo._(_=>_.Bar)._(_=>_.Baz)看起来有点奇怪,但相当简洁:)

现场样本:https://dotnetfiddle.net/9R8bku