C# if-null-then-null 表达式

发布于 2024-10-04 05:49:13 字数 459 浏览 6 评论 0原文

只是为了好奇/方便:C# 提供了我所知道的两个很酷的条件表达式功能:

string trimmed = (input == null) ? null : input.Trim();

string trimmed = (input ?? "").Trim();

经常遇到另一个这样的表达式:

如果输入引用为 null,则输出应该为 null。否则,输出应该是访问输入对象的方法或属性的结果。

我在第一个示例中正是这样做的,但是 (input == null) ? null :input.Trim() 非常冗长且不可读。

对于这种情况还有其他条件表达式吗,或者我可以优雅地使用 ?? 运算符吗?

Just for curiosity/convenience: C# provides two cool conditional expression features I know of:

string trimmed = (input == null) ? null : input.Trim();

and

string trimmed = (input ?? "").Trim();

I miss another such expression for a situation I face very often:

If the input reference is null, then the output should be null. Otherwise, the output should be the outcome of accessing a method or property of the input object.

I have done exactly that in my first example, but (input == null) ? null : input.Trim() is quite verbose and unreadable.

Is there another conditional expression for this case, or can I use the ?? operator elegantly?

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

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

发布评论

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

评论(7

溺渁∝ 2024-10-11 05:49:13

像 Groovy 的空安全解引用运算符之类的东西?

string zipCode = customer?.Address?.ZipCode;

我猜想 C# 团队已经研究过这个问题,发现它并不像人们想象的那样简单优雅地设计......尽管我还没有听说过问题的细节。

恐怕我现在不相信该语言中有任何这样的事情......而且我还没有听说过任何相关计划,尽管这并不是说它在某个时候不会发生。

编辑:它现在将成为 C# 6 的一部分,作为“空条件运算符”。

Something like Groovy's null-safe dereferencing operator?

string zipCode = customer?.Address?.ZipCode;

I gather that the C# team has looked at this and found that it's not as simple to design elegantly as one might expect... although I haven't heard about the details of the problems.

I don't believe there's any such thing in the language at the moment, I'm afraid... and I haven't heard of any plans for it, although that's not to say it won't happen at some point.

EDIT: It's now going to be part of C# 6, as the "null-conditional operator".

不奢求什么 2024-10-11 05:49:13

恐怕目前我们只能在您不想重复的情况下编写扩展方法。

public static string NullableTrim(this string s)
{
   return s == null ? null : s.Trim();
}

Currently we can only write an extension method if you don't want to repeat yourself, I'm afraid.

public static string NullableTrim(this string s)
{
   return s == null ? null : s.Trim();
}
终难愈 2024-10-11 05:49:13

您可以选择自定义 Nullify 类或 NullSafe 扩展方法,如下所述:http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/

用法如下如下:

//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name

//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
                       m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
                      .NullSafe( b => b.Name );

You can choose between a custom Nullify class or a NullSafe extension method as described here: http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/

The usage will be as follows:

//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name

//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
                       m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
                      .NullSafe( b => b.Name );
无边思念无边月 2024-10-11 05:49:13

作为解决方法,您可以使用基于 Maybe monad< /a>.

public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
    if (instance == null)
        return default(Tout);
    else
        return Output(instance);
}

这样使用它:

int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());

As a workaround you can use this which is based on Maybe monad.

public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
    if (instance == null)
        return default(Tout);
    else
        return Output(instance);
}

Use it this way:

int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());
久隐师 2024-10-11 05:49:13

没有任何内置内容,但如果您愿意,您可以将其全部包装在扩展方法中(尽管我可能不会打扰)。

对于这个具体示例:

string trimmed = input.NullSafeTrim();

// ...

public static class StringExtensions
{
    public static string NullSafeTrim(this string source)
    {
        if (source == null)
            return source;    // or return an empty string if you prefer

        return source.Trim();
    }
}

或更通用的版本:

string trimmed = input.IfNotNull(s => s.Trim());

// ...

public static class YourExtensions
{
    public static TResult IfNotNull<TSource, TResult>(
        this TSource source, Func<TSource, TResult> func)
    {
        if (func == null)
            throw new ArgumentNullException("func");

        if (source == null)
            return source;

        return func(source);
    }
}

There's nothing built-in, but you could wrap it all up in an extension method if you wanted (although I probably wouldn't bother).

For this specific example:

string trimmed = input.NullSafeTrim();

// ...

public static class StringExtensions
{
    public static string NullSafeTrim(this string source)
    {
        if (source == null)
            return source;    // or return an empty string if you prefer

        return source.Trim();
    }
}

Or a more general-purpose version:

string trimmed = input.IfNotNull(s => s.Trim());

// ...

public static class YourExtensions
{
    public static TResult IfNotNull<TSource, TResult>(
        this TSource source, Func<TSource, TResult> func)
    {
        if (func == null)
            throw new ArgumentNullException("func");

        if (source == null)
            return source;

        return func(source);
    }
}
自控 2024-10-11 05:49:13

我遇到了同样的问题,我写了一些小扩展方法:

public static TResult WhenNotNull<T, TResult>(
    this T subject, 
    Func<T, TResult> expression)
    where T : class
{
    if (subject == null) return default(TResult);
    return expression(subject);
}

public static TResult WhenNotNull<T, TResult>(
    this T subject, Func<T, TResult> expression,
    TResult defaultValue)
    where T : class
{
    if (subject == null) return defaultValue;
    return expression(subject);
}

public static void WhenNotNull<T>(this T subject, Action<T> expression)
    where T : class
{
    if (subject != null)
    {
        expression(subject);
    }
}

你像这样使用它;

string str = null;
return str.WhenNotNull(x => x.Length);

or

IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);

or

object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());

还有可空类型的重载。

I had the same problem I wrote a few little extension methods:

public static TResult WhenNotNull<T, TResult>(
    this T subject, 
    Func<T, TResult> expression)
    where T : class
{
    if (subject == null) return default(TResult);
    return expression(subject);
}

public static TResult WhenNotNull<T, TResult>(
    this T subject, Func<T, TResult> expression,
    TResult defaultValue)
    where T : class
{
    if (subject == null) return defaultValue;
    return expression(subject);
}

public static void WhenNotNull<T>(this T subject, Action<T> expression)
    where T : class
{
    if (subject != null)
    {
        expression(subject);
    }
}

You use it like this;

string str = null;
return str.WhenNotNull(x => x.Length);

or

IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);

or

object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());

There are also overloads for nullable types.

一身仙ぐ女味 2024-10-11 05:49:13

我知道 Jon Skeet 已经回答了这个问题,但这个示例可能是 Elvis 运算符 ?. (又名 空条件成员访问运算符)的更清晰

string? someValue = (input == null) ? null : input.Trim()

示例相当于...

string? someValue = input?.Trim();

“谢谢你,非常感谢” - 埃尔维斯·普雷斯利

I know this was already answered by Jon Skeet but this example might be a little more clear example of the Elvis operator ?. (aka the null-conditional member access operator)

string? someValue = (input == null) ? null : input.Trim()

is equivalent to...

string? someValue = input?.Trim();

"Thank You, Thank You Very Much" - Elvis Presley

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