“null this”是否可以使用扩展方法?

时间:2022-09-23 08:09:07

So, I really enjoy using extension methods.. maybe a bit too much. So, I'm going to ask about my latest enjoyment to ensure that I'm not going too far.

所以,我真的很喜欢使用扩展方法..也许有点太多了。所以,我会问我最近的享受,以确保我不会走得太远。

Scenario is that we have a Guid? variable that gets passed in. If the variable is null or Guid.Empty, then we want to use a different Guid. So, I wrote an extension method to make it read like English:

情景是我们有一个Guid?传入的变量。如果变量为null或Guid.Empty,那么我们想要使用不同的Guid。所以,我写了一个扩展方法,让它像英文一样读:

    internal static Guid OrIfEmpty(this Guid? guid, Guid other)
    {
        if (!guid.HasValue || guid.Value == Guid.Empty)
        {
            return other;
        }
        return guid.Value;
    }

This automatically implies that a "null this" will not throw an exception. For instance, this will work:

这自动意味着“null this”不会抛出异常。例如,这将工作:

((Guid?)null).OrIfEmpty(other);

This is not possible without using extension methods, and in my opinion can be quite misleading. However, it's just so concise and clean! So, what do you think? Is this an acceptable thing to do or could it be too confusing to other programmers?

如果不使用扩展方法,这是不可能的,在我看来可能会产生误导。然而,它只是如此简洁和干净!所以你怎么看?这是可以接受的事情,还是对其他程序员来说太混乱了?

Also, I'm sure there will be other scenarios where I do things like this and checking this for null, but this is the best example I have right now.

此外,我确信会有其他情况我会做这样的事情并将其检查为null,但这是我现在最好的例子。

Note: I'm not really asking about this Guid? business in particular. I'm asking more about the overall pattern implemented (having an extension method where the this can be null)

注意:我真的不是在问这个Guid吗?特别是生意。我要求更多关于实现的整体模式(有一个扩展方法,其中可以为null)

5 个解决方案

#1


5  

This is not possible without using extension methods

如果不使用扩展方法,这是不可能的

Sure it is, just make is a regular static method call (which is all extension methods are):

当然是,只是make是一个常规的静态方法调用(这是所有的扩展方法):

in my opinion can be quite misleading

在我看来,可能会产生误导

I agree, since it looks like you're calling an instance method on a null instance. It could be worse:

我同意,因为它看起来像是在null实例上调用实例方法。还可能会更糟糕的:

string s = null;
string n = s.OrIfEmpty("empty");

At first glance this looks like an obvious NullReferenceException waiting to happen, but it compiles and works as designed.

乍一看,这看起来像一个明显的NullReferenceException等待发生,但它编译并按设计工作。

Since your question is really just soliciting opinions, there's not one right answer, but I certainly would be cautious and document the extension method to indicate that the this parameter could be null. Or (as @quezalcoatl implies) rename it to be more explicit that it supports null values:

由于您的问题实际上只是征求意见,因此没有一个正确的答案,但我当然会谨慎并记录扩展方法以指示此参数可以为null。或者(正如@quezalcoatl暗示的那样)将其重命名为更明确它支持null值:

internal static Guid OrIfNullOrEmpty(this Guid? guid, Guid other)

#2


3  

I personally I think there will be much more developers that understand better and faster (so in the end means the code is cleaner):

我个人认为会有更多的开发人员更好更快地理解(所以最终意味着代码更清晰):

if (!guid.HasValue || guid.Value == Guid.Empty)
{
    return other;
}

Rather than:

而不是:

((Guid?)null).OrIfEmpty(other);

So it depends if you're coding for yourself or what you write could be supported by others. Personally I don't think the value added is worth the "weirdness" :)

所以这取决于你是为自己编码还是你所写的东西可以得到其他人的支持。就个人而言,我认为增值不值得“怪异”:)

#3


1  

In general, an extension method should check for null values. After all, an extension method is nothing more than a static method with some syntactic sugar added so that the compiler can treat it like an instance method.

通常,扩展方法应检查空值。毕竟,扩展方法只不过是一个静态方法,添加了一些语法糖,因此编译器可以像处理实例方法一样对待它。

For example, if you have this:

例如,如果你有这个:

public static class MyExtensions
{
    public static IEnumerable<TSource> Frob<TSource>(this TSource source)
    {
        // do stuff here
    }
}

You can then call it two different ways:

然后你可以用两种不同的方式调用它:

var foo = new List<int>();
var bar = foo.Frob();  // called like an instance method
var barby = MyExtensions.Frob(foo); // called like a static method

Whereas with a normal instance method you can assume that this is not null, you can't make that assumption with an extension method.

而使用普通实例方法,您可以假设这不是null,您不能使用扩展方法进行该假设。

#4


1  

I do not see any problem with that. Just recall the

我没有看到任何问题。回想一下

string.IsNullOrEmptyOrWhitespace

string.IsNullOrEmptyOrWhitespace

that comes from stdlib.

来自stdlib。

In general, it depends on what will you do on that null case. If you use the function in a normal way, and if the function behaves normally with that special case - all's ok. But if your function gets into debug mode and starts reconfiguring the system, well, you've crossed the Principle-of-Least-Astonishment and that is not good

一般来说,这取决于你将在那个空案例上做什么。如果以正常方式使用该功能,并且该功能在该特殊情况下正常运行 - 一切正常。但是,如果你的函数进入调试模式并开始重新配置系统,那么,你已经越过了最小的原则 - 这是不好的

-- note: as @JeppeStigNielsen accurately pointed out, the INOEOW is not an extension method in the current version of .Net. I am sure that I had it a few times as extension method, but most probably it was on some CTP version or maybe it was custom addon for old versions of .Net where it didn't exist at all. Sorry for the confusion! Nevertheless, "it's all about proper naming" stil holds! :)

- 注意:正如@JeppeStigNielsen准确指出的那样,INOEOW不是当前版本的.Net中的扩展方法。我确信我有几次作为扩展方法,但很可能它是在一些CTP版本或者它可能是旧版本的.Net的自定义插件,它根本不存在。对困惑感到抱歉!尽管如此,“这都是关于正确命名的”stil持有! :)

#5


0  

I think this is OK. Note that the example with Nullable<Guid> is not that bad, since so-called null of type Nullable<Guid> is a real and existing value of Nullable<Guid>, not "nothing".

我觉得这没关系。请注意,使用Nullable 的示例并不是那么糟糕,因为Nullable 类型的所谓null是Nullable 的实际值和现有值,而不是“无”。

That's why you can also use instance methods on this kind of "null", as in

这就是为什么你也可以在这种“null”上使用实例方法,如

Guid? g = null;
g.GetValueOrDefault();  // OK; real instance method

Using this with a reference type is even more "strange":

使用它与引用类型更加“奇怪”:

internal static string OrIfEmpty(this string str, string other)
{
  return string.IsNullOrEmpty(str) ? other : str;
}

Because then you can call it on a "real" null:

因为那时你可以在“真正的”空值上调用它:

string s = null;
s.OrIfEmpty("unspecified");  // OK; s is a true null reference

#1


5  

This is not possible without using extension methods

如果不使用扩展方法,这是不可能的

Sure it is, just make is a regular static method call (which is all extension methods are):

当然是,只是make是一个常规的静态方法调用(这是所有的扩展方法):

in my opinion can be quite misleading

在我看来,可能会产生误导

I agree, since it looks like you're calling an instance method on a null instance. It could be worse:

我同意,因为它看起来像是在null实例上调用实例方法。还可能会更糟糕的:

string s = null;
string n = s.OrIfEmpty("empty");

At first glance this looks like an obvious NullReferenceException waiting to happen, but it compiles and works as designed.

乍一看,这看起来像一个明显的NullReferenceException等待发生,但它编译并按设计工作。

Since your question is really just soliciting opinions, there's not one right answer, but I certainly would be cautious and document the extension method to indicate that the this parameter could be null. Or (as @quezalcoatl implies) rename it to be more explicit that it supports null values:

由于您的问题实际上只是征求意见,因此没有一个正确的答案,但我当然会谨慎并记录扩展方法以指示此参数可以为null。或者(正如@quezalcoatl暗示的那样)将其重命名为更明确它支持null值:

internal static Guid OrIfNullOrEmpty(this Guid? guid, Guid other)

#2


3  

I personally I think there will be much more developers that understand better and faster (so in the end means the code is cleaner):

我个人认为会有更多的开发人员更好更快地理解(所以最终意味着代码更清晰):

if (!guid.HasValue || guid.Value == Guid.Empty)
{
    return other;
}

Rather than:

而不是:

((Guid?)null).OrIfEmpty(other);

So it depends if you're coding for yourself or what you write could be supported by others. Personally I don't think the value added is worth the "weirdness" :)

所以这取决于你是为自己编码还是你所写的东西可以得到其他人的支持。就个人而言,我认为增值不值得“怪异”:)

#3


1  

In general, an extension method should check for null values. After all, an extension method is nothing more than a static method with some syntactic sugar added so that the compiler can treat it like an instance method.

通常,扩展方法应检查空值。毕竟,扩展方法只不过是一个静态方法,添加了一些语法糖,因此编译器可以像处理实例方法一样对待它。

For example, if you have this:

例如,如果你有这个:

public static class MyExtensions
{
    public static IEnumerable<TSource> Frob<TSource>(this TSource source)
    {
        // do stuff here
    }
}

You can then call it two different ways:

然后你可以用两种不同的方式调用它:

var foo = new List<int>();
var bar = foo.Frob();  // called like an instance method
var barby = MyExtensions.Frob(foo); // called like a static method

Whereas with a normal instance method you can assume that this is not null, you can't make that assumption with an extension method.

而使用普通实例方法,您可以假设这不是null,您不能使用扩展方法进行该假设。

#4


1  

I do not see any problem with that. Just recall the

我没有看到任何问题。回想一下

string.IsNullOrEmptyOrWhitespace

string.IsNullOrEmptyOrWhitespace

that comes from stdlib.

来自stdlib。

In general, it depends on what will you do on that null case. If you use the function in a normal way, and if the function behaves normally with that special case - all's ok. But if your function gets into debug mode and starts reconfiguring the system, well, you've crossed the Principle-of-Least-Astonishment and that is not good

一般来说,这取决于你将在那个空案例上做什么。如果以正常方式使用该功能,并且该功能在该特殊情况下正常运行 - 一切正常。但是,如果你的函数进入调试模式并开始重新配置系统,那么,你已经越过了最小的原则 - 这是不好的

-- note: as @JeppeStigNielsen accurately pointed out, the INOEOW is not an extension method in the current version of .Net. I am sure that I had it a few times as extension method, but most probably it was on some CTP version or maybe it was custom addon for old versions of .Net where it didn't exist at all. Sorry for the confusion! Nevertheless, "it's all about proper naming" stil holds! :)

- 注意:正如@JeppeStigNielsen准确指出的那样,INOEOW不是当前版本的.Net中的扩展方法。我确信我有几次作为扩展方法,但很可能它是在一些CTP版本或者它可能是旧版本的.Net的自定义插件,它根本不存在。对困惑感到抱歉!尽管如此,“这都是关于正确命名的”stil持有! :)

#5


0  

I think this is OK. Note that the example with Nullable<Guid> is not that bad, since so-called null of type Nullable<Guid> is a real and existing value of Nullable<Guid>, not "nothing".

我觉得这没关系。请注意,使用Nullable 的示例并不是那么糟糕,因为Nullable 类型的所谓null是Nullable 的实际值和现有值,而不是“无”。

That's why you can also use instance methods on this kind of "null", as in

这就是为什么你也可以在这种“null”上使用实例方法,如

Guid? g = null;
g.GetValueOrDefault();  // OK; real instance method

Using this with a reference type is even more "strange":

使用它与引用类型更加“奇怪”:

internal static string OrIfEmpty(this string str, string other)
{
  return string.IsNullOrEmpty(str) ? other : str;
}

Because then you can call it on a "real" null:

因为那时你可以在“真正的”空值上调用它:

string s = null;
s.OrIfEmpty("unspecified");  // OK; s is a true null reference