簡體   English   中英

在繼承類型中使用C#dynamic進行方法調用

[英]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 ,它們被intstring參數重載。 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()方法的上下文中沒有任何意義。

同樣在我上面的簡化示例中。 的編譯時類型testProgram ,就像類型thisStart()Program 因此, DoSomething(long)重載在該上下文中不可見,並且無法調用。

如果希望它可見,則需要將其添加到基類,或者確保用於調用DoSomething()的引用靜態類型為CoolProgram 需要注意的是,因為正如聲明的方法, protectedCoolProgram ,你也不得不改變交通方便,如果你想要去改變靜態類型的參考的途徑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.

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