簡體   English   中英

我可以從C#委托中返回對新對象實例的引用嗎?

[英]Can I return a reference to new object instance from a C# delegate?

我正在學習/試驗C#中的一些功能模式,我遇到了一個無法解釋的問題。 我確信這是一個簡單的答案(我希望),但我很難看到它。 可能與閉包等有關,而我無法開箱即用,隱藏了我的答案!

這是我的實驗:我試圖從函數委托中返回一個特定類的全新實例。

public class Foo{
    string A { get; set ; }
}

static void Main( string[] args ){
    // the delegate...
    Func<Foo,bool> someFunc = o => {
        o = new Foo { A = "A new instance of o?" };
        return true;
    };

    Foo foo = null;   // was hoping to replace this via delegate
    var myFunc = someFunc;
    var result = myFunc( foo );

    if ( foo == null )
        Console.WriteLine( "foo unchanged :-(" );
    else
        Console.WriteLine( foo.A ); // hoping for 'A new instance of o?'

當然,我只是在我的輸出中得到“foo不變:-(”。我在測試中做了一個小的變化,我傳入一個非空的Foo實例並修改了屬性“A”(vs返回一個新實例)和哪個工作正常(也就是說,我可以改變一個現有的對象就像我在將對象引用傳遞給函數時所期望的那樣)我似乎無法從我的委托中獲得一個新的實例。

所以? 我只是在代碼中做錯了嗎? 這可以完成嗎? 很想知道為什么這不起作用。

形式參數ofoo值的副本 ; 變異o不會改變foo 這和你說的時候一樣:

int x = 1;
int y = x;
y = 2;

這不會改變x y是的值的副本 x ,而不是一個別名 x

你是在思考這個問題。 如果你想擁有一個改變本地的委托,那么只需編寫一個改變本地的委托:

Foo foo = null;   // was hoping to replace this via delegate
Action mutateFoo = () => { foo = new Foo() { A = "whatever"}; };
mutateFoo();
if ( foo == null )
    Console.WriteLine( "foo unchanged :-(" );
else
    Console.WriteLine( foo.A );

如果您想要做的就是改變變量,那么改變變量。 如果您只想執行副作用,則無需向代理傳遞任何內容。

我注意到你說你正在嘗試功能模式。 請記住,函數式編程不鼓勵變量變異,所以你可能會在這里走錯路。

您可以返回Foo作為lambda表達式的返回值:

Func<Foo> someFunc = o =>
{
    return new Foo { A = "A new instance of o?" };
};

或者如果你真的需要返回一個bool Tuple<bool, Foo>你可以返回一個Tuple<bool, Foo>

Func<Tuple<bool, Foo>> someFunc = o =>
{
    return Tuple.Create(true, new Foo { A = "A new instance of o?" });
};

或者,如果你真的確定你想要那個,你可以用out參數聲明你自己的自定義Func like委托:

delegate TResult FuncOut<T, TResult>(out T arg);
FuncOut<Foo, bool> someFunc = (out Foo o) =>
{
     o = new Foo { A = "A new instance of o?" };
     return true;
};

Foo foo;
var result = someFunc(out foo);

但我不建議這樣做。

您正在將Foo對象的引用(即地址)傳遞給您的委托。 該地址被分配給委托的參數o (將其視為局部變量)。 當您在委托中更改Foo對象時,您將引用對象並更改該地址上的內容。 這就是對象變化的原因。

但是當你將新地址分配給委托的局部變量(即參數)時,你只是丟失了傳遞給委托的原始Foo對象的地址。 賦值后,局部變量只保存新Foo對象的地址。 它不會影響調用者的foo變量,它仍然擁有另一個地址。

暫無
暫無

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

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