C# extension method for setting to new instance if null

只愿长相守 提交于 2019-12-12 12:16:17

问题


I have the following extension methods to help me check and instantiate objects if they are null. The top two work just fine but they are not very useful.

    public static bool IsNull<T>(this T t)
    {
        return ReferenceEquals(t, null);
    }

    public static T NewIfNull<T>(this T t, Func<T> createNew)
    {
        if (t.IsNull<T>())
        {
            return createNew();
        }

        return t;
    }

    public static void Ensure<T>(this T t, Func<T> createNew)
    {
        t = t.NewIfNull<T>(createNew);
    }

Ultimately I would like to do something like

IList<string> foo;
...
foo.Ensure<IList<string>>(() => new List<string>());

The Ensure method however does not achieve the desired effect, which is setting foo to a instance of List<string> if it is null and basically set it to itself otherwise.

if you know now I can tweak the Ensure method to achieve this I would appreciate the help.

Thanks, Tom


回答1:


You need to distinguish between objects and variables. An object can never be null - the value of a variable can be. You're not trying to change something about an object (which would work) - you're trying to change the value of the caller's variable.

However, arguments are passed by value by default, which means that your extension method changes the parameter (the variable declared within the method), but this has no effect on the caller's variable. Normally you'd be able to change the parameter to ref to achieve pass-by-reference semantics, but extension methods can't have a ref or out first parameter.

As others have said, using the null-coalescing operator (??) is a better bet. Note that in this expression:

foo = foo ?? new List<string>();

the new list is not constructed unless foo is null. The right hand operand of ?? is not evaluated unless it needs to be.




回答2:


So you're attempting to duplicate the null-coalescing operator?

foo = foo ?? new List<string>();



回答3:


Your Ensure method doesn't work because you're just setting a local reference variable (t) but not returning it. If Ensure returned t, you could do:

var list2 = list1.Ensure<List<string>>();

However, you don't need that because you can just use the ?? operator:

var list2 = list1 ?? new List<string>();



回答4:


Your Ensure method does not do anything because assigning something new to a parameter t does not change anything for the caller when t is not a ref (or out) parameter. Instead, saying

IList<string> foo;
...
foo = foo.NewIfNull(() => new List<string>());

will probably work, but as others have said isn't the most beautiful way of doing this.



来源:https://stackoverflow.com/questions/10967421/c-sharp-extension-method-for-setting-to-new-instance-if-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!