簡體   English   中英

使用擴展方法實例化類的實例

[英]Instantiating an instance of a class using an extension method

這段代碼背后的想法是,如果該類設置為null,它使用擴展方法來實例化類的實例。 代碼很簡單,但不起作用(它編譯並運行,但最后對象引用仍為null )。

誰有人建議為什么?

以下代碼使用具有單個string屬性的簡單類SomeClass

class SomeClass
{
    public string SomeProperty { get; set; }
}


static class ExtensionMethods
{
    public static void InitialiseObjectIfNull<T>(this T obj)
        where T : class, new()
    {
        if (obj == null) obj = new T();
    }
}

class Program
{
    static void Main(string[] args)
    {
        SomeClass someClass = null;

        someClass.InitialiseObjectIfNull();

        // someClass is still null - but why??
    }
}

(關於這是否適當使用擴展方法的討論應該被認為超出了問題的范圍!我有興趣理解為什么這種方法不起作用)

編輯

仔細觀察這個問題不是關於擴展方法的問題,而是關於在傳遞帶有或不帶ref關鍵字的引用類型時發生的事情的更多信息。

以下函數將導致為調用者初始化傳遞的obj

static void InitialiseObjectIfNull<T>(ref T obj) where T : class, new()
{
    if (obj == null) obj = new T();
}

InitialiseObjectIfNull<SomeClass>(ref someClass); // someClass will be initialised

以下函數不會導致為調用者初始化傳遞的obj

static void InitialiseObjectIfNull<T>(T obj) where T : class, new()
{
    if (obj == null) obj = new T();
}

InitialiseObjectIfNull<SomeClass>(someClass); // someClass will not be initialised

但是......我們在這里處理一個引用類型,那么如果不使用ref關鍵字,CLR對new d obj做了什么? 據推測它只是收集垃圾......

EDIT2

好的,我們回到這里的基礎知識。 請考慮以下代碼:

class Program
{
    static void SetProperty(SomeClass someClass)
    {
        someClass.SomeProperty = "Bar";
    }

    static void Main(string[] args)
    {
        SomeClass someClass = new SomeClass { SomeProperty = "Foo" };

        SetProperty(someClass);

        // someClass.SomeProperty now equals "Bar"
    }
}

注意: someClass未使用ref關鍵字傳遞,但其屬性的值仍然為調用者更改。 這是我期望看到的。

但是,更改SetProperty函數如下:

static void SetProperty(SomeClass someClass)
{
    someClass = new SomeClass { SomeProperty = "Bar" };
}

...並且調用者不會看到someClass任何更改。

你需要返回值; 擴展方法不是對this參數的ref

static class ExtensionMethods
{
    public static T InitialiseObjectIfNull<T>(this T obj)
        where T : class, new()
    {
        return obj ?? new T();            
    }
}

然后你需要:

someClass = someClass.InitialiseObjectIfNull();

就個人而言,我希望直接做到這一點會更簡單...:

if(someClass == null) someClass = new SomeClass();

要么

someClass = someClass ?? new SomeClass();

this T obj需要是一個ref參數。 由於這是不允許的( MSDN或C#In Depth p258,Skeet),你不能。

不過,我建議你不要把這個想法推得太遠。 這似乎是擴展方法的一個令人困惑的應用,特別是當替代方案仍然是一個短的一行。

擴展方法只是語法糖:

ExtensionMethods.InitialiseObjectIfNull(someClass);

你通過值傳遞someClass ,因此在InitialiseObjectIfNull體內分配它將沒有任何效果,除非你通過引用傳遞someClass ,在擴展方法的情況下你不能這樣做:你不能通過引用在this T obj傳遞this

這不起作用,因為obj參數未聲明通過引用傳遞。 不幸的是,你不能將參數聲明為“this ref T obj”,它不受支持......我知道,我昨天試過了;)

你可以這樣做:

static class ExtensionMethods
{
    public static T InitialiseObjectIfNull<T>(this T obj)
        where T : class, new()
    {
        return obj ?? new ();
    }
}

class SomeClass
{
    public string SomeProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        SomeClass someClass = null;

        someClass = someClass.InitialiseObjectIfNull();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM