第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

重寫方法上的C??蛇x參數

重寫方法上的C??蛇x參數

千巷貓影 2019-12-25 15:46:14
似乎在.NET Framework中,重寫該方法時,可選參數存在問題。以下代碼的輸出是:“ bbb”“ aaa”。但是我期望的輸出是:“ bbb”“ bbb”。是否有針對此的解決方案。我知道可以通過方法重載來解決,但想知道這樣做的原因。該代碼在Mono中也可以正常工作。class Program{    class AAA    {        public virtual void MyMethod(string s = "aaa")        {            Console.WriteLine(s);        }        public virtual void MyMethod2()        {            MyMethod();        }    }    class BBB : AAA    {        public override void MyMethod(string s = "bbb")        {            base.MyMethod(s);        }        public override void MyMethod2()        {            MyMethod();        }    }    static void Main(string[] args)    {        BBB asd = new BBB();        asd.MyMethod();        asd.MyMethod2();    }}
查看完整描述

3 回答

?
慕少森

TA貢獻2019條經驗 獲得超9個贊

這里需要注意的一件事是,每次都會調用覆蓋的版本。將替代更改為:


public override void MyMethod(string s = "bbb")

{

  Console.Write("derived: ");

  base.MyMethod(s);

}

輸出為:


derived: bbb

derived: aaa

類中的方法可以執(zhí)行以下一項或多項操作:


它定義了其他代碼調用的接口。

它定義了一個在調用時執(zhí)行的實現(xiàn)。

它可能不會兩者都做,因為抽象方法只會做前者。


在BBB調用MyMethod()調用方法定義在AAA。


由于中存在覆蓋BBB,因此調用該方法將導致實現(xiàn)BBB被調用。


現(xiàn)在,中的定義AAA將兩件事告知調用代碼(嗯,還有一些無關緊要的地方)。


簽名void MyMethod(string)。

(對于支持該語言的語言)單個參數的默認值為"aaa",因此,MyMethod()如果在找不到該方法匹配的形式的形式的代碼時MyMethod(),可以用對MyMethod(“ aaa”)的調用來替換它。

因此,這就是調用的BBB作用:編譯器看到對的調用MyMethod(),未找到方法,MyMethod()但確實找到了方法MyMethod(string)。它還可以看到在定義它的地方有一個默認值“ aaa”,因此在編譯時它將其更改為對的調用MyMethod("aaa")。


從內部BBB,即使在中被覆蓋,也AAA被認為AAA是定義方法的地方BBB,以便可以覆蓋它們。


在運行時,MyMethod(string)使用參數“ aaa”調用。因為存在一個覆蓋的形式,所以該形式被調用,但是不使用“ bbb”來調用它,因為該值與運行時實現(xiàn)無關,而與編譯時定義無關。


添加this.更改將檢查哪個定義,從而更改調用中使用的參數。


編輯:為什么這對我來說似乎更直觀。


就個人而言,由于我所說的是直觀的東西,因此只能是個人的,我發(fā)現(xiàn)它更直觀,原因如下:


如果我正在編碼,BBB那么無論是調用還是覆蓋MyMethod(string),我都認為這是“正在做的AAA事情”,這是BBB在“正在做的AAA事情” 上做的事情,但實際上AAA都是在做事情。因此,無論是調用還是覆蓋,我都將意識到它就是AAA定義的事實MyMethod(string)。


如果我要調用使用過的代碼BBB,我會想到“使用BBB東西”。我可能不太了解最初是在中定義的AAA,因此我可能會認為這只是實現(xiàn)細節(jié)(如果我也沒有使用AAA附近的接口)。


編譯器的行為符合我的直覺,這就是為什么當初讀這個問題時,我覺得Mono有一個錯誤。經考慮,我看不到任何一個如何比另一個更好地實現(xiàn)指定的行為。


盡管如此,盡管如此,在保持個人水平的同時,我絕不會將可選參數與抽象,虛擬或重寫方法一起使用,并且如果要覆蓋其他人使用的參數,我會匹配它們。


查看完整回答
反對 回復 2019-12-25
?
慕娘9325324

TA貢獻1783條經驗 獲得超4個贊

您可以通過以下方式消除歧義:


this.MyMethod();

(在中MyMethod2())


它是否是一個漏洞是棘手的。它看起來確實不一致。Resharper會警告您根本不要更改覆蓋中的默認值,如果這樣做會有所幫助; p當然,resharper 還會告訴您this.多余,并愿意為您刪除它……這會改變行為-因此,resharper也并不完美。


看起來確實有可能成為編譯器錯誤,我將授予您。我需要看真仔細,以確保...這里的埃里克·當你需要他,是吧?


編輯:


這里的重點是語言規(guī)范;讓我們看看第7.5.3節(jié):


例如,用于方法調用的候選集不包括標記為重寫的方法(第7.4節(jié)),并且如果派生類中的任何方法均適用(第7.6.5.1節(jié)),則基類中的方法也不是候選者。


(實際上,第7.4節(jié)顯然沒有override考慮方法)


這里有一些沖突...。它指出如果派生類中有適用的方法,則不使用基本方法-這將導致我們進入派生方法,但與此同時,它表示標記override的方法沒有考慮過的。


但是,第7.5.1.1節(jié)指出:


對于在類中定義的虛擬方法和索引器,參數列表是從函數成員的最特定的聲明或重寫中選取的,從接收方的靜態(tài)類型開始,并搜索其基類。


然后第7.5.1.2節(jié)解釋了在調用時如何評估值:


在函數成員調用(第7.5.4節(jié))的運行時處理期間,參數列表的表達式或變量引用按從左到右的順序求值,如下所示:


...(剪斷)...


當從具有相應可選參數的函數成員中省略參數時,將隱式傳遞函數成員聲明的默認參數。由于這些參數始終是恒定的,因此它們的評估不會影響其余參數的評估順序。


這明確突出表明它正在查看參數列表,該列表先前在§7.5.1.1中定義為來自最具體的聲明或重寫。似乎這是第7.5.1.2節(jié)中提到的“方法聲明”是合理的,因此傳遞的值應該是從最派生的到靜態(tài)類型。


這可能表明:csc有一個錯誤,并且應該使用派生版本(“ bbb bbb”),除非它被限制(通過base.或強制轉換為基本類型)查看基本方法聲明(第7.6.8節(jié))。 )。


查看完整回答
反對 回復 2019-12-25
?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

在我看來,這似乎是個錯誤。我相信它已被明確指定,并且其行為應與您使用顯式this前綴調用該方法的行為相同。


我已將示例簡化為僅使用單個虛擬方法,并顯示了調用了哪種實現(xiàn)以及參數值是什么:


using System;


class Base

{

    public virtual void M(string text = "base-default")

    {

        Console.WriteLine("Base.M: {0}", text);

    }   

}


class Derived : Base

{

    public override void M(string text = "derived-default")

    {

        Console.WriteLine("Derived.M: {0}", text);

    }


    public void RunTests()

    {

        M();      // Prints Derived.M: base-default

        this.M(); // Prints Derived.M: derived-default

        base.M(); // Prints Base.M: base-default

    }

}


class Test

{

    static void Main()

    {

        Derived d = new Derived();

        d.RunTests();

    }

}

因此,我們需要擔心的是RunTests中的三個調用。前兩個調用的規(guī)范的重要部分是7.5.1.1節(jié),該節(jié)討論在查找相應參數時要使用的參數列表:


對于在類中定義的虛擬方法和索引器,參數列表是從函數成員的最特定的聲明或重寫中選取的,從接收方的靜態(tài)類型開始,并搜索其基類。


以及7.5.1.2節(jié):


當從具有相應可選參數的函數成員中省略參數時,將隱式傳遞函數成員聲明的默認參數。


“相應的可選參數”是將7.5.2關聯(lián)到7.5.1.1的位。


對于M()和this.M(),參數列表都應該是Derived接收者的靜態(tài)類型Derived,實際上,您可以告訴編譯器將其視為編譯早期的參數列表,就好像您在中都將參數強制設置為一樣。調用失敗-因此調用要求參數在中具有默認值,但隨后將其忽略!Derived.M()M()Derived


確實,情況變得更糟:如果您在中提供參數的默認值,Derived但在中將Base其設為必需,則調用 M()最終將null用作參數值。如果沒有別的,我想證明這是一個錯誤:該null值不能來自任何有效的地方。(這是null由于它是string類型的默認值;它始終僅將默認值用于參數類型。)


與base.M(),它表示,該規(guī)范交易部分7.6.8 ,以及作為非虛擬行為,表達被視為((Base) this).M(); 因此,使用基本方法確定有效參數列表是完全正確的。這意味著最后一行是正確的。


只是為了使想要查看上述真正奇怪的錯誤的人更輕松,其中使用了未在任何地方指定的值:


using System;


class Base

{

    public virtual void M(int x)

    {

        // This isn't called

    }   

}


class Derived : Base

{

    public override void M(int x = 5)

    {

        Console.WriteLine("Derived.M: {0}", x);

    }


    public void RunTests()

    {

        M();      // Prints Derived.M: 0

    }


    static void Main()

    {

        new Derived().RunTests();

    }

}


查看完整回答
反對 回復 2019-12-25
  • 3 回答
  • 0 關注
  • 541 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號