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

本文关键字:对象 一个对象 变量 包含 访问 | 更新日期: 2023-09-27 17:49:01

我有以下两个类。地址包含地址列表。方法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。如果发生这种情况,调用将失败,因为它通过空对象引用ID。在本例中,我想返回null。

为了解决这个问题,我使用以下代码:
if(obj.MailingAddress == null)
{
    I? = null;
}
else
{
    I? = obj.MailingAddress.ID;
}

是否有一种方法可以调用obj.MailingAddress.ID,如果MailingAddress为空,则返回null,而无需执行上述if语句。

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

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

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

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

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

但是,在c# 6中您可以使用?操作符,有时称为安全导航操作符:

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

作为额外的注意事项,您可以使用空对象模式。你可以从这里学习它,也可以使用这个模式。Null Object模式的使用简化了代码,使其更不容易出错。

这是c# 5中c# 6 Null传播语法的一个愚蠢的实现:

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