Ссылка на константное поле другого класса при использовании универсального свойства, названного в честь него - PullRequest
0 голосов
/ 14 мая 2019

Представьте, что у меня есть структура классов, подобная этой:

public interface IArbitraryQualifier {
    int Qualification { get; }
}
public class ArbitraryQualifier : IArbitraryQualifier {
    public const int MIN_QUALITY = 1;

    public int Qualification { get; }    
}
public class Person {
    public IArbitraryQualifier ArbitraryQualifier { get; }
    public bool AmIARealBoy 
    { 
      get 
      { 
        return this.ArbitraryQualifier.Qualification >= ArbitraryQualifier.MIN_QUALITY; 
      } 
    }
}

Как мне ссылаться на постоянное поле MIN_QUALITY в классе ArbitraryQualifier из класса Person? Он продолжает генерировать ошибку IDE0009 («... не содержит определения для ...»), которая предлагает мне «добавить квалификацию« this »или« me »».

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

Обратите внимание, что это также происходит для абстрактных классов и универсальных типов, но не для конкретных типов. Например, здесь нет ошибки компиляции:

public class ArbitraryQualifier {
    public const int MIN_QUALITY = 1;

    public int Qualification { get; }    
}
public class Person {
    public ArbitraryQualifier ArbitraryQualifier { get; }
    public bool AmIARealBoy 
    { 
      get 
      { 
        return this.ArbitraryQualifier.Qualification >= ArbitraryQualifier.MIN_QUALITY; 
      }
    }
}

Кроме того, почему это компилируется, когда другие нет?

Ответы [ 3 ]

2 голосов
/ 14 мая 2019

Если класс зависит от IArbitraryQualifier, он не должен ничего знать о реализации, за исключением того, что он реализует IArbitraryQualifier.Это означает, что Person не должен знать, что реализация IArbitraryQualifier имеет константу с именем MIN_QUALITY.Он должен знать только то, что объявлено в интерфейсе.

Например, что если мы создадим другую реализацию IArbitraryQualifier:

public class OtherQualifier : IArbitraryQualifier 
{
    public int Qualification { get; }  
}

... и затем сделаем это:

var person = new Person();
person.ArbitraryQualifier  = new OtherQualifier();

Теперь нет постоянной MIN_QUALITY.

Основополагающий принцип заключается в том, что в 99% случаев мы не хотим ничего знать об объекте, кроме типа, к которому он относится.объявленЕсли объявленный тип свойства IArbitraryQualifier, то все члены этого интерфейса имеют значение.Мы не хотим знать подробности о реализациях этого интерфейса, таких как другие свойства, методы, константы и т. Д.

Несколько возможных решений:

  • Поместите константу в другое место,возможно в Person классе.ArbitraryQualifier не использует константу, так почему она должна содержать константу?(Это будет мой первый выбор.) Поместите константу в класс, который нуждается в этом.
  • Измените тип свойства с IArbitraryQualifier на ArbitraryQualifier.Если вы знаете, что вам нужно работать с этим конкретным классом (включая его константу), используйте его.
  • Наименее желательно: добавьте открытое свойство в интерфейс IArbitraryQualifier, чтобы все реализации имели это свойство.Это не имеет никакого смысла в этом случае, если только нет какой-то причины, почему реализации IArbitraryQualifier должны предоставлять это значение.
1 голос
/ 14 мая 2019

Хотя Ответ Руфу решает проблему , он не объясняет, почему проблема существует.

Проблема существует, потому что ваша собственность:

public IArbitraryQualifier ArbitraryQualifier { get; }

То же имя , что и ваш конкретный класс:

public class ArbitraryQualifier

Поскольку код содержится в классе Person, компилятор разрешает имена в (локально = this) переменные с локальной областью (var ... и т. Д.), Затем в локальные поля / свойства, затем в доступные именованные классы в текущее пространство имен, затем вверх по цепочке пространств имен.

Переименование имени свойства в локальном / этот класс также решает проблему.

public interface IArbitraryQualifier
{
    int Qualification
    {
        get;
    }
}

public class ArbitraryQualifier : IArbitraryQualifier
{
    public const int MIN_QUALITY = 1;
    public int Qualification
    {
        get;
    }
}

public class Person
{
    public IArbitraryQualifier ArbitraryQualifier2
    {
        get;
    }

    public bool AmIARealBoy
    {
        get
        {
            return this.ArbitraryQualifier2.Qualification >= ArbitraryQualifier.MIN_QUALITY;
        }
    }
}
1 голос
/ 14 мая 2019

Вы можете обратиться к полному имени класса, если хотите получить доступ к статическому свойству, которое является namespace.classname.propertyname.

Например, приведенное ниже пространство имен Test является частью полного доменного имени (а также иллюстрирует другой способ записи свойства только для чтения с использованием синтаксиса тела выражения ):

namespace Test
{
    public interface IArbitraryQualifier
    {
        int Qualification { get; }
    }

    public class ArbitraryQualifier : IArbitraryQualifier
    {
        public const int MIN_QUALITY = 1;

        public int Qualification { get; }
    }

    public class Person
    {
        public IArbitraryQualifier ArbitraryQualifier { get; }
        public bool AmIARealBoy => 
            ArbitraryQualifier.Qualification >= Test.ArbitraryQualifier.MIN_QUALITY;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...