Что такое слежка?

Что означает термин затенение в C #? Я прочитал эту ссылку, но не совсем понял ее.


person Community    schedule 23.03.2009    source источник
comment
Не все объясняют вещи точно так же, как они? Разве в школе не было учителей, которые, по вашему мнению, были лучше других?   -  person    schedule 23.03.2009
comment
Следует отметить, что затенение - это термин VB - C # называет это сокрытием.   -  person Adam Lassek    schedule 23.03.2009
comment
Я всегда слышал, как это называется затенением в JS, C, Java.   -  person Juan Mendes    schedule 12.02.2011
comment
Вот довольно хорошее видео по этому поводу. youtube.com/watch?v=xmjOPCnSE30   -  person Chris Lees    schedule 07.06.2013


Ответы (11)


Затенение скрывает метод в базовом классе. Используя пример в вопросе, который вы связали:

class A 
{
   public int Foo(){ return 5;}
   public virtual int Bar(){return 5;}
}
class B : A
{
   public new int Foo() { return 1;}
   public override int Bar() {return 1;}
}

Класс B переопределяет виртуальный метод Bar. Он скрывает (затеняет) невиртуальный метод Foo. При переопределении используется ключевое слово переопределить. Затенение выполняется с помощью ключевого слова новое.

В приведенном выше коде, если вы не использовали ключевое слово new при определении метода Foo в классе B, вы получите это предупреждение компилятора:

'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
person Jim Mischel    schedule 23.03.2009
comment
Какое у этого функциональное назначение? Например, зачем вам что-то скрывать, а не отменять? - person sab669; 28.10.2015
comment
@ sab669: Представьте, что вы хотите переопределить невиртуальный метод. На самом деле вы не можете отменить его, поэтому вместо этого вы затеняете его. Это не идеальное решение, потому что он не во всех случаях действует как переопределенный виртуальный метод, но при вызове из производного класса он будет работать должным образом. Это относительно редко, но когда вам это нужно, вам это действительно нужно. - person Jim Mischel; 28.10.2015
comment
А, значит, он просто существует как. Ну, этот метод не виртуальный, и по той или иной причине я не могу сделать его виртуальным, так что новый должен будет что-то делать? - person sab669; 28.10.2015
comment
@ sab669: Это одно применение. См. stackoverflow.com/questions/1193848/ и stackoverflow.com/questions/14461725/ для дополнительных Информация. - person Jim Mischel; 28.10.2015

  • Переопределение: переопределение существующего метода в базовом классе
  • Затенение: создание совершенно нового метода с той же сигнатурой, что и в базовом классе
person Kent Boogaart    schedule 23.03.2009
comment
Новый метод - с такой же подписью или? - person User; 23.03.2009
comment
Обратите внимание, что с помощью затенения вы можете изменить тип возвращаемого значения. - person Dave Cousineau; 16.10.2015

Предположим, у меня есть базовый класс, реализующий виртуальный метод:

public class A
{
    public virtual void M() { Console.WriteLine("In A.M()."); }
}

У меня также есть производный класс, который также определяет метод M:

public class B : A
{
    // could be either "new" or "override", "new" is default
    public void M() { Console.WriteLine("In B.M()."); }
}

Теперь предположим, что я напишу такую ​​программу:

A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();

У меня есть два разных варианта реализации. Поведение по умолчанию - вызвать версию M. (Это идентично поведению, если вы применили ключевое слово "new" к B.M().)

Это называется «затенением», когда у нас есть метод с тем же именем, но с другим поведением при вызове из базового класса.

В качестве альтернативы мы могли указать "override" на B.M(). В этом случае alpha.M() назвал бы версию М.

person mqp    schedule 23.03.2009

Затенение заключается в сокрытии метода базового класса с новым определением в дочернем классе.

Разница между скрытием и переопределением связана со способом вызова методов.

Таким образом, когда виртуальный метод переопределяется, адрес вызова таблицы вызовов методов базового класса заменяется адресом дочерней процедуры.

С другой стороны, когда метод скрыт, новый адрес добавляется в таблицу вызовов методов дочернего класса.

Когда вызывается рассматриваемый метод:

  1. Получается тип класса таблицы вызова методов, если мы вызываем со ссылкой на базовый класс, тогда получается таблица методов базового класса, если у нас есть ссылка на дочерний класс, тогда получается таблица методов дочернего класса.
  2. Метод ищется в таблице, если он найден, то выполняется вызов, в противном случае ищется таблица методов базового класса.

Если мы вызываем метод со ссылкой на дочерний класс, то поведение такое же, если метод был переопределен, адрес метода будет найден в базовом классе, если метод был скрыт, адрес метода будет найден в дочерний класс, и, поскольку он уже найден, поиск в таблице базового класса выполняться не будет.

Если мы вызываем метод со ссылкой на базовый класс, поведение меняется. При переопределении, поскольку адрес метода перезаписывает запись базового класса, мы будем вызывать дочерний метод, даже если он содержит ссылку на базовый класс. При затенении таблица методов базового класса (которая является единственной видимой, поскольку мы храним ссылку на базовый класс) содержит адрес виртуального метода, и поэтому будет вызван метод базового класса.

В общем, затенение - плохая идея, так как оно вносит различие в поведение экземпляра в зависимости от ссылки на него.

person Jorge Córdoba    schedule 23.03.2009

Расширяя правильный ответ Кента

При устранении неоднозначности, когда будет вызван метод, мне нравится думать о затенении и переопределении с помощью следующих

  • Затенение: вызываемый метод зависит от типа ссылки в точке вызова.
  • Переопределение: вызываемый метод зависит от типа объекта в точке вызова.
person JaredPar    schedule 23.03.2009

Вот статья MSDN о теневом использовании. Примеры языков представлены на Visual Basic (к сожалению, в MSDN нет эквивалентной страницы C #), но в целом он имеет дело с концепциями и, надеюсь, все равно поможет вам понять.

Изменить: похоже, что есть статья на C # о теневом копировании, за исключением того, что в C # это называется скрытием. Кроме того, эта страница предлагает хороший обзор.

person Noldorin    schedule 23.03.2009
comment
Это потому, что в C # это называется скрытием: msdn.microsoft.com /en-us/library/aa691133(VS.71).aspx - person Adam Lassek; 23.03.2009

Если вы хотите скрыть метод базового класса, используйте переопределение в базе [виртуальный метод в базе]

если вы хотите скрыть метод дочернего класса, используйте новый в базе [невиртуальный метод в базе] -> тень

Base B=new Child()

B.VirtualMethod() -> Вызов метода дочернего класса

B.NonVirtualMethod() -> Вызов метода базового класса

person Mathew M    schedule 11.04.2012

Переопределение: одно и то же имя и одни и те же параметры, по-разному реализованные в подклассах.

  • Если он рассматривается как DerivedClass или BaseClass, он использует производный метод.

Затенение: одно и то же имя и точно такие же параметры, по-разному реализованные в подклассах.

  • При обработке как DerivedClass используется производный метод.
  • если рассматривается как BaseClass, он использует базовый метод.
person Kamran Bigdely    schedule 13.04.2018

Надеюсь, это краткое объяснение поможет.

Shadowing - Заменяет весь элемент родительского класса

class InventoryAndSales
{
    public int InvoiceNumber { get; set; }
}

//if someone calls for this class then the InvoiceNumber type is now object 
class NewInventoryAndSales : InventoryAndSales
{
    public new object InvoiceNumber { get; set; }
}



Overriding - заменяет только реализацию. Он не заменяет тип данных, который он не заменяет, например, у вас есть переменная, она не преобразует ее в метод, поэтому, если есть метод, он будет использовать этот метод и изменит только реализацию

 class InventoryAndSales
    {
        public virtual int GetTotalSales(int a, int b)
        {
            return a + b;
        }
    }


    class NewInventoryAndSales : InventoryAndSales
    {
        //it replaces the implementation in parent class
        public override int GetTotalSales(int a, int b)
        {
            return a * b;
        }
    }
person davinceleecode    schedule 14.06.2018

Затенение - это не то, о чем я бы беспокоился о понимании или реализации, если оно не "соответствует" проблеме действительно хорошо. Я видел, как он используется неправильно и вызывает странные логические ошибки гораздо чаще, чем при правильном использовании. Я думаю, что основная причина заключается в том, что когда программист забывает указать переопределения в сигнатуре метода, предупреждение компилятора предложит новое ключевое слово. Я всегда считал, что вместо этого следует рекомендовать использовать переопределение.

person Jeremy    schedule 23.03.2009
comment
Это похоже на комментарий. - person Neolisk; 12.03.2015

 private static int x = 10;


static void Main(string[] args)
    { int x = 20;
        if (Program.x == 10)
        {
            Console.WriteLine(Program.x);
        }
        Console.WriteLine(x);}

Выход:

10 20

person dhaval8087    schedule 11.01.2012
comment
Это не отвечает на вопрос - person alu; 19.03.2014