扩展方法而不是空对象模式

发布于 2024-07-09 03:50:52 字数 904 浏览 6 评论 0原文

我想知道使用扩展方法来避免检查层次结构中的 null 。 示例:

// GetItems(), GetFirstOrDefault(), GetProduct(), GetIDProduct() are extension methods like:
public static SomeType GetSomeProperty( this XYZ obj ) {
    if ( object.ReferenceEquals( obj, null ) ) { return default( SomeType ); }
    return obj.SomeProperty;
}

// the code with extension methods
Guid? idProduct = this.Invoice.GetItems().GetFirstOrDefault().GetProduct().GetIDProduct();
// instead of
Guid? idProduct = null;
Invoice invoice = this.Invoce;
if ( null != invoice ) {
    InvoiceItems items = invoice.Items;
    if ( null != items && items.Count > 0 ) {
        InvoiceItem item = items[0];
        if ( null != item ) {
            idProduct = item.IDProduct();
        }
    }
}

我知道,有可用的空对象模式,但使用此类扩展方法的解决方案看起来更好。

您认为这个解决方案是好还是坏(因为设计不好/好、清晰度等等)?

请投票“好”或“坏”,以及您为什么这么认为。 帖子被标记为社区。

I'm wondering to using extension method to avoid checking for null in hierarchy.
The example:

// GetItems(), GetFirstOrDefault(), GetProduct(), GetIDProduct() are extension methods like:
public static SomeType GetSomeProperty( this XYZ obj ) {
    if ( object.ReferenceEquals( obj, null ) ) { return default( SomeType ); }
    return obj.SomeProperty;
}

// the code with extension methods
Guid? idProduct = this.Invoice.GetItems().GetFirstOrDefault().GetProduct().GetIDProduct();
// instead of
Guid? idProduct = null;
Invoice invoice = this.Invoce;
if ( null != invoice ) {
    InvoiceItems items = invoice.Items;
    if ( null != items && items.Count > 0 ) {
        InvoiceItem item = items[0];
        if ( null != item ) {
            idProduct = item.IDProduct();
        }
    }
}

I know, there is available Null Object pattern, but the solution with this type of extension methods looks better.

Do you think, this solution is good or bad (because bad/good design, lucidity, whatever else)?

Please vote "Good" or "Bad" and why do you think so.
Posts are flaged as community.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

眉黛浅 2024-07-16 03:50:52

我会理智地做这件事:

Guid? idProduct = null;
Invoice invoice = this.Invoce;

if (invoice != null && 
    invoice.Items != null &&
    invoice.Items.Count > 0 &&
    invoice.Items[0] != null) 
{
   idProduct = invoice.Items[0].IDProduct();
}

I'd just do it sanely:

Guid? idProduct = null;
Invoice invoice = this.Invoce;

if (invoice != null && 
    invoice.Items != null &&
    invoice.Items.Count > 0 &&
    invoice.Items[0] != null) 
{
   idProduct = invoice.Items[0].IDProduct();
}
给妤﹃绝世温柔 2024-07-16 03:50:52

我将此投票为“对该解决方案不感兴趣”。

我对我的实体模型类使用空对象模式很满意。

I vote this as "not-interested-in-that-solution".

I'm fine with a Null-Object-Pattern for my entity model classes.

梦过后 2024-07-16 03:50:52

破坏了语义实例方法。 对于调用者来说,扩展方法看起来像实例方法,因此应该像它们一样表现。 当你像这样破坏语义时,代码将更难理解和维护,它的行为会让大多数开发人员感到惊讶。

This breaks the semantics of an instance method. Extension methods look like instance methods to the callers, and as such should behave like them. When you break semantics like this, the code will be harder to understand and maintain, its behavior will surprise most developers.

七七 2024-07-16 03:50:52

阅读这段代码时,让我印象深刻的第一件事是

GetFirstOrDefault().GetProduct()

它打破了两个习惯用法:1)使用 Jon 指出的 Get 风格方法,2)“取消隐藏”Null Object 提供的抽象。 OrDefault 让我成为代码的读者,并让我思考 null ,而

GetFirst().GetProduct()

不会。 是的,空对象和扩展方法替代方案的要点之一是减轻读者和/或维护者的负担。 否则为什么要这样做呢?

The first thing that struck me when reading this code was

GetFirstOrDefault().GetProduct()

It breaks two idioms: 1) using Get style methods as noted by Jon, and 2) "unhiding" the abstraction provided by Null Object. The OrDefault engages me as a reader of your code and makes me think about null where

GetFirst().GetProduct()

would not. And yes, one of the points of Null Object and your extension method alternative are to unburden the reader and/or maintainer. Or else why do either?

趴在窗边数星星i 2024-07-16 03:50:52

Java 和 .net 的一个限制是,没有任何内容可以清楚地标识引用类型的存储位置在语义上是否应被视为保存对象的值,而不是识别对象(当然,从计算机的角度来看,所有此类存储位置都是后者)。 尽管如此,有些类型(如String)的存储位置通常被视为保存一个值,而其他类型(如StringBuilder)的存储位置通常被视为保存值。被视为识别应对其执行操作的对象。

如果不是因为 Nullable 上的 struct 约束,并且类类型可以指定实例成员应该运行(this 为 null) )当在空对象上调用时,我认为这是某些类型的绝佳模式。 虽然通常不可能明智地为可变类类型指定默认值,但对于许多不可变类型来说,具有合理的默认行为是完全合理的(例如,default(string).Length 可能返回零) 。 不幸的是,.net 语言没有办法指定属性和方法应该可用于 null 对象,但至少扩展方法可以在这方面提供一些帮助。

One limitation with Java and .net is that there's nothing which clearly identifies whether a storage location of reference type should be regarded semantically as holding an object's value, versus identifying an object (from the computer's perspective, of course, all such storage locations do the latter). Nonetheless, there are some types (like String) for which a storage location would normally be regarded as holding a value, and others (like StringBuilder) for which a storage location would be regarded as identifying an object upon which operations should be performed.

Were it not for the struct constraint on Nullable<T>, and if class types could specify that instance members should run (with this being null) when invoked on a null object, I would regard that as an excellent pattern for some types. While it's generally not possible to sensibly specify a default value for a mutable class type, for many immutable types it would be entirely reasonable to have sensible default behavior (e.g. default(string).Length could return zero). Unfortunately, .net languages do not have a means of specifying that properties and methods should be usable on null objects, but at least extension methods can help a little in that direction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文