Как всегда вызывать новейшее поле класса C # - PullRequest
0 голосов
/ 12 мая 2018

Я был озадачен поведением ключевого слова new в C #, так как оно, похоже, не полностью переопределяет родительское значение, вот пример:

    public static void Main(string[] args)
    {
        A test = new B();

        Console.WriteLine(test.s);
    }

    public class A {

        public string s = "A";
    }

    public class B : A{
        public new string s = "B";
    }

Теперь я ожидал, что "B" будет напечатано, но вместо этого я получил "A"

Как я могу всегда вызывать новое свойство, независимо от того, какой класс его обновляет, вместо исходного?

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

Ключевое слово new в основном скрывает члена под новым членом с тем же именем.Однако этот новый член с таким же именем существует только в подклассе B, а не в базовом классе A. Таким образом, вы не заметите, что test.s содержит «B», если вы сначала не произвели приведение test к B.

public static void Main(string[] args)
{
    A test = new B();

    Console.WriteLine(test.s); // A

    B test2 = test as B;

    Console.WriteLine(test2.s); // B
}

public class A 
{
    public string s = "A";
}

public class B : A
{
    public new string s = "B";
}

Если вы хотите, чтобы элемент был заменен , вам нужно использовать ключевое слово override.Однако вы не можете переопределить поля, только методы и свойства.Попробуйте это:

public class A
{
    protected virtual string s { get => "A"; }
}

public class B : A
{
    protected override string s { get => "B"; }
}

public static void Main(string[] args)
{
    A test = new B();

    Console.WriteLine(test.s); // will print B
}

Ключевое слово virtual в A.s указывает, что это свойство может быть переопределено.

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

0 голосов
/ 12 мая 2018

Как уже отмечалось, ключевое слово new будет только скрывать значение, а не переопределять его.Чтобы сделать это, вам нужно использовать ключевое слово override, которое нельзя использовать в полях, но можно использовать в свойствах, например:

public static Main(string[] args)
{
    A test = new B();
    Console.WriteLine(test.S);    // Prints "B"
}

public class A
{
    protected string s;
    public virtual string S { get => "A"; set => s = value; }
}
public class B : A
{
    public override string S { get => "B"; set => s = value; }
}

Это, вероятно, самое близкоето, что вы ожидали, но мы должны ввести поле поддержки, чтобы иметь возможность изменить значение S.Если вы не планируете делать это, вы можете просто использовать public virtual string S => "A"; и сделать его доступным только для чтения.

Однако, это, вероятно, не предполагаемое использование переопределения свойств.Скорее всего, в функциях get или set есть что-то другое:

public class A
{
    public virtual string S 
    {
        // Do Something
    }
}
public class B : A
{
    public override string S
    {
        // Do something else
    }
}

Поскольку все, что вы делаете, это изменение значений, то, вероятно, лучше сделать это вконструктор.

public class A
{
    public string S { get; set; } = "A";
}
public class B : A
{
    public B() => S = "B";
}

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

0 голосов
/ 12 мая 2018

Для методов и свойств вы можете сделать это, заменив new на override. override фактически переопределяет метод, в то время как new только скрывает его.

То же самое относится к полям, но вы не можете использовать override с полями.

Но если вы посмотрите внимательно, вам нужно переопределить начальное значение s. В обоих классах s можно изменить позже.

Чтобы изменить начальное значение, просто напишите конструктор:

public B() {
    s = "B";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...