The_Unknown_Member Ответов: 1

[C#] почему я могу получить доступ к полям базового класса только из конструктора производного класса ?


Мне интересно, как работает этот код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp_Practicing
{
    class Parent
    {
        public string name;
        
        public Parent()
        {
            Console.WriteLine("Hello from the parent constructor");
        }
    }

    class Child : Parent
    {
        public Child()
        {
            Console.WriteLine("Hello from the child constructor"); 
            name = "Bob";
            Console.WriteLine("My name is: {0}", name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Child c = new Child();
        }
    }
}


Также то же самое происходит, если я использую this.name (но как это работает, разве ключевое слово "this" не относится к членам только в (в моем примере) дочернем классе ???)


Но этот код не будет работать:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp_Practicing
{
    class Parent
    {
        public string name;
        
        public Parent()
        {
            Console.WriteLine("Hello from the Parent constructor");
        }
    }

    class Child : Parent
    {
        name = "Bob"; 
    }

    class Program
    {
        static void Main(string[] args)
        {
            Child c = new Child();
        }
    }
}


И здесь возникает вопрос, почему он не работает ?

Что я уже пробовал:

Задавая вопрос здесь в CodeProject.com потому что я очень запутался, когда это случилось со мной, и не могу понять, что именно происходит с этим кодом.

1 Ответов

Рейтинг:
2

F-ES Sitecore

Первый пример работает, потому что Child является производным от Parent, поэтому он имеет все свойства Parent, включая переменную "name". Второй пример не работает, потому что это недопустимый c#. Класс может непосредственно содержать объявления переменных или функции, он не может непосредственно содержать код, код должен быть "в" чем-то (в рабочем примере он находится в конструкторе). Хотя это сработало бы

class Child : Parent
{
    public void MyFunction()
    {
        name = "Bob";
    }
}


The_Unknown_Member

Но если инициализировать поле " имя " в родительском классе, то оно будет работать. Так почему же возникает проблема, когда я хочу инициализировать поле " имя " из производного класса ? Я просто не могу понять

F-ES Sitecore

В родительском классе вы определяете переменную

публичное строковое имя;

это законно. В дочернем классе вы устанавливали его значение в коде

имя = " Боб";

что не является юридическим синтаксисом. Он не находится в функции, так когда же этот код будет запущен? Если он должен запускаться при создании класса, то он должен быть в конструкторе.

The_Unknown_Member

Но если я объявляю и инициализирую поле в одном операторе, оно работает. Например:

public string name = "Bob"; / / работает

но это не сработает:

public string name; / / объявление поля
name = "Bob"; / / инициализация поля в том же классе

F-ES Sitecore

Это потому, что компилятор распознает это

общественного строка имя = "Вася";

и делает с ним что-то особенное. Он определяет переменную, а также перемещает бит "=Bob " в специальное событие инициализации\конструктор, чтобы он знал, как использовать все значения по умолчанию. Чтобы сделать это, вам нужно придерживаться этого конкретного синтаксиса. Для компилятора этот код находится здесь

публичное строковое имя;
имя = " Боб";

ничем не отличается от

публичное строковое имя;
for (int i; i < 10; i++){}

Вы определяете переменную, а затем пишете код. Компилятор не может быть обеспокоен тем, что цикл for является недопустимым, но "name=Bob" является объявлением, поэтому его следует переместить в конструктор, поэтому вместо этого вы должны придерживаться допустимого синтаксиса, предоставляемого языком.

The_Unknown_Member

Я все понял. Спасибо, что объяснили мне это! :)