2010-07-16 24 views
4
void Afunction(int* outvar) 
{ 
    if(outvar) 
     *outvar = 1337; 
} 

注意的質量:它允許您可選地通過引用傳遞變量,以便它可以由函數設置。什麼是相當於通過地址在C#

我最親密的猜測是(裁判中斷?outvar)

但產生REF(INT?)NOT(REF INT)?這是我需要的

這個功能幾乎不是c或C++的一個很少使用的特性,所以我認爲必須有一些等價的? 編輯: 所以讓我嘗試一個很好的例子,我認爲Colision檢查函數是一個主要的例子,其中主要測試是兩個對象是否接觸,然後是投影向量的可選輸出,計算投影向量需要額外的時間,所以如果他們想要的話,你只想做它,另一方面,它通常會使用大量的計算信息進行碰撞測試。

bool Collide(colObject obj1, colObject obj2, Vector3* projection) 
{ 

    //do a bunch of expensive operations to determine if there is collision 
    if(!collided)return false; 
    if(projection != NULL) 
    { 
     //do more expensive operations, that make use of the above operations already done, 
     //to determine the proj vect 
     *proj = result; 
    } 
    return true; 
} 

請注意,我只是目前移植的C++代碼到C#,所以我可能沒有,雖然任何真正的「開箱即用」解決方案

+2

你期待ref(int?)和(ref int)之間的行爲差​​異是什麼? – 2010-07-16 02:00:00

+2

也許如果你描述你正試圖解決的問題,可能會有一個更明顯的c#py解決方案。現在看起來你正在試圖讓c#適合C++編程範例。 – 2010-07-16 02:07:16

+0

我明白'ref'並不是真正的類型修飾符嗎?是,但理想情況下,我想要一個?包含對int的引用的類型,而不是對?的引用。包含一個int的類型,所以我可以實現上面提到的功能,我基本上希望能夠通過引用傳遞,但也能夠通過'null'使參數可選,就像你使用?類型mod。 – matt 2010-07-16 02:09:02

回答

5

,你可以在C#中得到的最好的是Action<int>,像這樣:

void MyFunction(Action<int> valueReceiver) { 
    if (valueReceiver != null) 
     valueReceiver(1337); 
} 

用法:

MyFunction(null); 
MyFunction(v => someVariable = v); 
+3

'Func '是一個函數,它將返回一個int並且不帶任何參數。你想要的是'動作'這需要一個int並且沒有返回值 – 2010-07-16 02:23:31

+2

@Grant - 有人注意到18分鐘?我認爲我們正在滑倒。 – ChaosPandion 2010-07-16 02:26:17

+0

@Grant,@ChaosPandion:謝謝;我需要更多的睡眠。 – SLaks 2010-07-16 02:28:51

0

嘗試out關鍵字。

void Afunction(out int outvar) { 
    outvar = 1337; 
} 

這不完全等同。例如,除非拋出該函數,否則必須將一個值分配給out參數。

+0

關鍵詞有'可選'有時我不需要outvar,所以在c我只是傳遞null,這允許函數知道是否需要outval,因此可以跳過一大堆計算if它不是 – matt 2010-07-16 02:01:54

1

我想不出該C代碼的直接翻譯。我認爲C#模式看起來更像是這樣的:

void Afunction() 
{ 
} 

void Afunction(out int outvar) 
{ 
    Afunction(); 
    outvar = 1337; 
} 
+0

他希望能夠跳過計算。 – SLaks 2010-07-16 02:07:12

+0

@SLaks:將計算放在'Afunction(out int outvar)'中。在'Afunction()'中放入任何不會被跳過的東西(如果有的話)。 – 2010-07-16 04:31:20

1

我覺得ref是更符合C代碼的意圖:

void Afunction(ref int refvar) { 
    refvar = 1337; 
} 

但你也可以訴諸unsafe

unsafe void Afunction(int* pvar) { 
    if (pvar != null) { 
    *pvar = 1337; 
    } 
} 
+0

我打算假設Windows Phone 7不支持不安全的代碼? – matt 2010-07-16 03:32:00

+0

而你會[右](http://stackoverflow.com/questions/1307012/net-micro-framework-unsafe-code/1307031#1307031)。 – 2010-07-16 13:12:33

3

這不是你想要的?

private void foo() 
{ 
    int? y = 0; 
    bar(ref y); 

    int? z = null; 
    bar(ref z); 

    // shows "y = 42, z = " 
    MessageBox.Show(string.Format("y = {0}, z = {1}", y, z)); 
} 

private void bar(ref int? varRef) 
{ 
    if (varRef != null) 
     varRef = 42; 
} 
+0

我也認爲這會非常接近。雖然它有點笨重。 – ChaosPandion 2010-07-16 02:44:23

5

這取決於你想在C++中使用那個指針。有四種東西你可以使用指針:

  1. 設置指針指向的變量的值。
  2. 獲取指針所指向的變量的值。
  3. 比較指針本身爲空
  4. 比較指針本身與另一個指針。

如果您想要做第一個,請將其設置爲「out」參數。

如果你想做前兩個,使它成爲一個「ref」參數。

如果你想要做的前三,那麼我通常在這種不幸的情況做的是:

sealed class Ref<T> 
{ 
    private Action<T> setter; 
    private Func<T> getter; 
    public Ref(Action<T> setter, Func<T> getter) 
    { 
     this.setter = setter; 
     this.getter = getter; 
    } 
    public T Value { get { return getter(); } set { setter(value); } } 
} 

,現在你可以說

void M(Ref<int> r) 
{ 
    if (r != null) // 3 
    { 
     Console.WriteLine(r.Value); // 2 
     r.Value = 123; // 1 
    } 
} 
... 
int x = 0; 
M(new Ref<int>(y=>{x=y;},()=>x); // pass a 'ref' to x 

然後我重構代碼,以便我不是處於一種爲了突出它的明確目的而必須傳遞某些東西的情況。

或者,簡單一點,但關於對變量的存儲不夠靈活:

class Ref<T> 
{ 
    public T Value { get; set; } 
} 
... M same as before ... 
Ref<int> x = new Ref<int>(); 
x.Value = 0; 
M(x); 

和您更大的靈活性,因爲代表們當然可以做更復雜的事情不僅僅是獲取和設置變量委託方案。

如果你想要所有四個:使用C++,而不是C#,或使用C#的不安全子集,並堅持指針。沒有簡單的方法可以比較正常C#中的引用。

0

我想你可以做的一件事是讓2個代理函數調用一個隱藏的函數,並附加一個額外的參數來告訴隱藏函數發生了什麼。

E.g.

private bool Collide(colObject obj1, colObject obj2, ref Vector3 projection, bool calcProjection) 
{ 

    //do a bunch of expensive operations to determine if there is collision 
    if(!collided)return false; 
    // Now instead of checking if projection is null, we just check if they requested it 
    if(calcProjection) 
    { 
     //do more expensive operations, that make use of the above operations already done, 
     //to determine the proj vect 
     *proj = result; 
    } 
    return true; 
} 

public bool Collide(colObject obj1, colObject obj2, ref Vector3 projection) 
{ 
    return Collide(obj1, obj2, ref projection, true); 
} 

public bool Collide(colObject obj1, colObject obj2) 
{ 
    Vector3 dummy; 
    return Collide(obj1, obj2, ref dummy, false); 
} 

不知道如何這會相比,這裏其他的答案進行,但看到如何大多數創建的中間對象,它應該是可比的。