![](/img/trans.png)
[英]Is it possible to pass a property as a ref parameter in a setter? c# (avoid “a property or indexer may not be passed as an out or ref parameter”.)
[英]A property or indexer may not be passed as an out or ref parameter
我收到上述錯誤,無法解決。 我用谷歌搜索了一下,但無法擺脫它。
我有 class BudgetAllocate
,其屬性是double
類型的budget
。
在我的dataAccessLayer
中,
在我的一堂課中,我正在嘗試這樣做:
double.TryParse(objReader[i].ToString(), out bd.Budget);
這是拋出此錯誤:
屬性或索引器不能在編譯時作為 out 或 ref 參數傳遞。
我什至試過這個:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
其他一切工作正常,並且存在層之間的引用。
其他人已經為您提供了解決方案,但至於為什么這是必要的:屬性只是方法的語法糖。
例如,當您使用 getter 和 setter 聲明名為Name
的屬性時,編譯器實際上會生成名為get_Name()
和set_Name(value)
。 然后,當您讀取和寫入此屬性時,編譯器會將這些操作轉換為對這些生成方法的調用。
當您考慮到這一點時,很明顯為什么您不能將屬性作為輸出參數傳遞 - 您實際上將傳遞對方法的引用,而不是對對象變量的引用,這是輸出參數所期望的。
索引器也存在類似的情況。
這是一個泄漏抽象的情況。 屬性實際上是一個方法,索引器的get和set訪問器被編譯為 get_Index() 和 set_Index 方法。 編譯器在隱藏這一事實方面做得非常出色,例如,它會自動將賦值給屬性轉換為相應的 set_Xxx() 方法。
但是當您通過引用傳遞方法參數時,這會變得很糟糕。 這需要 JIT 編譯器傳遞一個指向所傳遞參數的內存位置的指針。 問題是,沒有一個,分配一個屬性的值需要調用 setter 方法。 被調用的方法無法區分傳遞的變量與傳遞的屬性之間的區別,因此無法知道是否需要方法調用。
值得注意的是,這實際上適用於 VB.NET。 例如:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
VB.NET 編譯器通過為 Run 方法自動生成以下代碼來解決這個問題,用 C# 表示:
int temp = Prop;
Test(ref temp);
Prop = temp;
您也可以使用哪種解決方法。 不太確定為什么 C# 團隊不使用相同的方法。 可能是因為他們不想隱藏潛在的昂貴的 getter 和 setter 調用。 或者當 setter 具有更改屬性值的副作用時,您將獲得完全無法診斷的行為,它們將在賦值后消失。 C# 和 VB.NET 的經典區別,C# 是“沒有驚喜”,VB.NET 是“如果可以的話,讓它工作”。
你不能使用
double.TryParse(objReader[i].ToString(), out bd.Budget);
用一些變量替換 bd.Budget。
double k;
double.TryParse(objReader[i].ToString(), out k);
將 out 參數放入局部變量,然后將變量設置為bd.Budget
:
double tempVar = 0.0;
if (double.TryParse(objReader[i].ToString(), out tempVar))
{
bd.Budget = tempVar;
}
更新:直接來自 MSDN:
屬性不是變量,因此不能作為輸出參數傳遞。
可能感興趣 - 您可以編寫自己的:
//double.TryParse(, out bd.Budget);
bool result = TryParse(s, value => bd.Budget = value);
}
public bool TryParse(string s, Action<double> setValue)
{
double value;
var result = double.TryParse(s, out value);
if (result) setValue(value);
return result;
}
這是一個非常古老的帖子,但我正在修改已接受的帖子,因為有一種我不知道的更方便的方法。
它被稱為內聯聲明並且可能一直可用(如在 using 語句中),或者它可能已在 C#6.0 或 C#7.0 中添加用於這種情況,不確定,但無論如何都像魅力一樣:
這個
double temp;
double.TryParse(objReader[i].ToString(), out temp);
bd.Budget = temp;
使用這個:
double.TryParse(objReader[i].ToString(), out double temp);
bd.Budget = temp;
所以預算是一種財產,對嗎?
而是首先將其設置為局部變量,然后將屬性值設置為該變量。
double t = 0;
double.TryParse(objReader[i].ToString(), out t);
bd.Budget = t;
通常,當我嘗試這樣做時,是因為我想設置我的屬性或將其保留為默認值。 在這個答案和dynamic
類型的幫助下,我們可以輕松創建一個字符串擴展方法來保持它的內襯和簡單。
public static dynamic ParseAny(this string text, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null && converter.IsValid(text))
return converter.ConvertFromString(text);
else
return Activator.CreateInstance(type);
}
像這樣使用;
bd.Budget = objReader[i].ToString().ParseAny(typeof(double));
// Examples
int intTest = "1234".ParseAny(typeof(int)); // Result: 1234
double doubleTest = "12.34".ParseAny(typeof(double)); // Result: 12.34
decimal pass = "12.34".ParseAny(typeof(decimal)); // Result: 12.34
decimal fail = "abc".ParseAny(typeof(decimal)); // Result: 0
string nullStr = null;
decimal failedNull = nullStr.ParseAny(typeof(decimal)); // Result: 0
可選
附帶說明一下,如果這是一個SQLDataReader
您還可以使用GetSafeString
擴展來避免來自讀取器的空異常。
public static string GetSafeString(this SqlDataReader reader, int colIndex)
{
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
public static string GetSafeString(this SqlDataReader reader, string colName)
{
int colIndex = reader.GetOrdinal(colName);
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
像這樣使用;
bd.Budget = objReader.GetSafeString(i).ParseAny(typeof(double));
bd.Budget = objReader.GetSafeString("ColumnName").ParseAny(typeof(double));
我遇到了同樣的問題(5 分鍾前),我使用帶有 getter 和 setter 的舊樣式屬性解決了它,它們的使用變量。 我的代碼:
public List<int> bigField = new List<int>();
public List<int> BigField { get { return bigField; } set { bigField = value; } }
所以,我只是使用了 bigField 變量。 我不是程序員,如果我誤解了這個問題,我真的很抱歉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.