[英]C# Generic and method
如何選擇好的方法(在下面的示例中,我將顯示2種無效的方法)。 我使用的不是帶有IF和IS的Object類型的變量來完成這項工作,但我試圖避免使用Object和裝箱/拆箱。 所以我以為Generic可以勝任這項工作,但我被困在這里。
這是一小段代碼,闡明了我的問題:
class Program
{
static void Main(string[] args)
{
Parser p = new Parser();
ObjectType1 o1 = new ObjectType1();
p.execute(o1);
Console.Read();
}
}
class Parser
{
public T execute<T>(T obj)
{
/*
if (obj is ObjectType1)
this.action((ObjectType1)obj);
else if (obj is ObjectType2)
this.action((ObjectType2)obj);
*/
this.action(obj);
return obj;
}
private void action(ObjectType1 objectType1)
{
Console.WriteLine("1");
}
private void action(ObjectType2 objectType2)
{
Console.WriteLine("2");
}
}
class ObjectType1
{
}
class ObjectType2
{
}
我不要界面和類。 抱歉。 我知道這不是問題的目的。
使用(ObjectType)obj進行投射不起作用,但是如果您這樣做:
if (obj is ObjectType1)
this.action(obj as ObjectType1);
else if (obj is ObjectType2)
this.action(obj as ObjectType1);
它有效...為什么?
而且...我無法為所有類型的execute方法重載,因為該方法來自Interface。 這就是為什么需要從此方法調用所有對象的原因。
不,你不能這樣做。 泛型不像C ++模板那樣工作-泛型方法僅編譯一次。 編譯器可用於重載解析的唯一信息是它在通用方法中了解的信息,而不管使用什么代碼。
作為顯示此示例的示例,以下是一些代碼,可能無法按預期運行:
using System;
class Test
{
static void Main()
{
string x = "hello";
string y = string.Copy(x);
Console.WriteLine(x==y); // Overload used
Compare(x, y);
}
static void Compare<T>(T x, T y) where T : class
{
Console.WriteLine(x == y); // Reference comparison
}
}
在不進一步了解您想做什么的情況下,很難說出最佳的前進方法。
您考慮過接口嗎?
interface IAction
{
void action();
}
class ObjectType1 : IAction
{
void action() {
Console.WriteLine("1");
}
}
class ObjectType2 : IAction
{
void action() {
Console.WriteLine("2");
}
}
class Parser
{
public IAction execute(IAction obj)
{
obj.action();
return obj;
}
}
此解決方案將需要更改所有業務邏輯對象以具有此接口。 在我看來,這確實不是要做的事情。 而且,在其他情況下,我總是更喜歡干凈的BusinessObject,而該Object的Interface與業務無關。 在我的問題中,我想要一個與Generic / Object / Delegate方法更相關的解決方案來實現。 謝謝你 此答案將不被接受。
我沒有嘗試過,但是您可以這樣做嗎?
public T execute<T>(T obj) { this.action((T)obj); return obj; }
(根據評論,不起作用)
要么
public T execute<T>(T obj)
{
this.action(obj as T);
return obj;
}
(根據評論,作品)
解析器類具有許多私有方法,這些私有方法由execute方法根據對象類型調用。 它需要重定向到好的方法。
編譯器將為您完成這項工作。 只需使用重載即可。
class Parser
{
public ObjectType1 action(ObjectType1 objectType1)
{
Console.WriteLine("1");
return objectType1;
}
public ObjectType2 action(ObjectType2 objectType2)
{
Console.WriteLine("2");
return objectType2;
}
}
class ObjectType1 { }
struct ObjectType2 { }
然后,調用:
Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());
沒有裝箱/拆箱,並且調用了適當的方法。
我知道您擔心裝箱/拆箱,因此此處可能涉及ValueType。
public T execute<T>(T obj)
{
this.action(obj);
return obj;
}
假設該操作正在修改obj,還假設該修改對調用方很重要 (這就是為什么要將值返回給調用方的原因)。 該代碼有一個討厭的傳遞值缺陷。
考慮以下代碼:
public int execute(int obj)
{
this.action(obj);
return obj;
}
public void action(int obj)
{
obj = obj + 1;
}
以這種方式調用。
int x = p.execute(1);
x是1,不是2。
IIRC,您可以使用“ where”子句來允許
public T execute<T>(T obj) where : /* somthing */
{
}
我總是不得不向Google透露自己的看法,因此我將其保留下來。
編輯:閱讀一些評論。 我不建議調用特定於類型的代碼。 而是將代碼放在虛函數中並調用它。 呼叫簽名可能會很長,但這就是自動完成的目的。
泛型發生在編譯時。 當您希望同一代碼應用於不同類型時,最好使用此方法。 它不是動態的,因此不會幫助您根據輸入類型在方法之間進行切換。
像David B的回復一樣,重載解析也可以,但是在編譯時也會發生。
更新中的代碼執行相同的操作。 它進行轉換(在仔細檢查類型之后),然后使用重載來解析該方法。
我覺得您想根據運行時輸入切換方法。
如果使用反射,則可以得到更動態的行為。
public object execute(object obj)
{
MethodInfo m = typeof(Parser).GetMethod(
"action",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type[] { obj.GetType() },
null);
m.Invoke(this, new object[] { obj });
return obj;
}
它可能有點脆弱,但是在示例中可以使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.