当子对象为空时,访问包含在另一个对象中的对象中的变量
本文关键字:对象 一个对象 变量 包含 访问 | 更新日期: 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