[英]Method call with C# dynamic in inherited type
我在嘗試擴展基類時注意到了一個意外的行為。 以下是此問題的示例:
public class Program
{
static void Main(string[] args)
{
var test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
本Program
定義了兩個方法DoSomething
,它們被int
和string
參數重載。 Start
方法創建一個which contains boxed values. After the definition, the elements will be iterated with casted
的對象數組which contains boxed values. After the definition, the elements will be iterated with casted
which contains boxed values. After the definition, the elements will be iterated with casted
動態` which contains boxed values. After the definition, the elements will be iterated with casted
。 這到目前為止工作正常(沒有長值)。
如果我創建一個額外的繼承類CoolProgram
並添加另一個方法到類型為long
的計划將引發RuntimeBinderException
,並告訴我,最好的過載是DoSomething(int)
CoolProgram
的方法沒有執行。
public class CoolProgram : Program
{
protected override void DoSomething(int i)
{
// This works
Console.WriteLine("Cool Int: " + i);
}
protected override void DoSomething(string str)
{
// This works
Console.WriteLine("Cool Str: " + str);
}
protected virtual void DoSomething(long i)
{
// This is a new method for long
Console.WriteLine("Long:" + i);
}
}
任何人都可以解釋這種行為或有解決方案嗎?
您的示例可以進一步簡化:
static void Main(string[] args)
{
Program test = new CoolProgram();
dynamic i = 1L;
test.DoSomething(i);
//test.Start();
}
問題是,就Start()
方法而言, this
具有類型Program
。 為DoSomething()
添加virtual
重載在Start()
方法的上下文中沒有任何意義。
同樣在我上面的簡化示例中。 的編譯時類型test
的Program
,就像類型this
中Start()
是Program
。 因此, DoSomething(long)
重載在該上下文中不可見,並且無法調用。
如果希望它可見,則需要將其添加到基類,或者確保用於調用DoSomething()
的引用靜態類型為CoolProgram
。 需要注意的是,因為正如聲明的方法, protected
在CoolProgram
,你也不得不改變交通方便,如果你想要去改變靜態類型的參考的途徑CoolProgram
。
最后,如果您真的想要完全動態類型解析,您可以:
private void Start()
{
dynamic this2 = this;
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
this2.DoSomething(dyn);
}
Console.ReadKey();
}
如上所述,上述內容當然要求DoSomething(long)
public
。
1)第一個問題是訪問修飾符受保護,因為您無法使用Long類型作為參數訪問重載方法。 我把它改成了內部現在可以訪問。
2)第二個問題是你正在創建子類CoolProgram對象但你要調用父類DoSomething方法你應該使用test.DoSomething(dyn); 並使子類對象全局化以在Start方法中訪問它。
public class Program
{
static CoolProgram test;
static void Main(string[] args)
{
test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
//test.DoSomething(21474836470);
foreach (var dyn in arr.Cast<dynamic>())
{
test.DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
// from here child class
public class CoolProgram : Program
{
protected override void DoSomething(int i)
{
// This works
Console.WriteLine("Cool Int: " + i);
base.DoSomething(i);
}
protected override void DoSomething(string str)
{
// This works
Console.WriteLine("Cool Str: " + str);
}
internal virtual void DoSomething(long i)
{
// This is a new method for long
Console.WriteLine("Long Int:" + i);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.