使用以其命名的通用属性时,引用另一个类的常量字段

时间:2019-05-13 21:36:25

标签: c# generics const

想象一下,我有一个与此类似的类结构:

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 个答案:

答案 0 :(得分:2)

如果一个类依赖于,那么它除了实现IArbitraryQualifier之外不应该对实现一无所知。这意味着IArbitraryQualifier不应该知道Person的实现具有名为IArbitraryQualifier的常量。它应该只知道接口中声明的内容。

例如,如果我们创建MIN_QUALITY的另一种实现怎么办:

IArbitraryQualifier

...然后执行以下操作:

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

现在没有var person = new Person(); person.ArbitraryQualifier = new OtherQualifier(); 常量。

基本原理是,在99%的时间内,我们不希望了解对象的任何信息,除了声明的类型。如果属性的声明类型为MIN_QUALITY,则该接口的成员就很重要。我们不想知道有关该接口实现的详细信息,例如其他属性,方法,常量等。

一些可能的解决方案:

  • 将常量放在IArbitraryQualifier类中的其他位置。 Person不使用常量,为什么它需要包含常量? (这是我的首选。)将常量放入需要它的类中。
  • 将属性类型从ArbitraryQualifier更改为IArbitraryQualifier。如果您知道需要使用该特定类(包括其常量),请使用该类。
  • 最不希望:在ArbitraryQualifier接口中添加一个公共属性,以便所有实现都具有该属性。在这种情况下,这似乎没有任何意义,除非出于某些原因,IArbitraryQualifier的实现必须提供该值。

答案 1 :(得分:1)

如果要访问静态属性HDC hScreenDC = GetWindowDC(ProgramData->TargetWnd); RECT Rect = {0}; GetWindowRect(ProgramData->TargetWnd, &Rect); INT Width = Rect.right - Rect.left; INT Height = Rect.bottom - Rect.top; HDC hMemoryDC = CreateCompatibleDC(hScreenDC); HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, Width, Height); HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemoryDC, hBitmap); BitBlt(hMemoryDC, 0, 0, Width, Height, hScreenDC, 0, 0, SRCCOPY | CAPTUREBLT); hBitmap = (HBITMAP) SelectObject(hMemoryDC, hOldBitmap); OpenClipboard(NULL); EmptyClipboard(); SetClipboardData(CF_BITMAP, hBitmap); CloseClipboard(); DeleteDC(hMemoryDC); DeleteDC(hScreenDC); ,可以引用该类的全限定名称。

例如,以下内容将名称空间namespace.classname.propertyname作为FQDN的一部分(并且还说明了使用expression-body syntax编写只读属性的另一种方式):

Test

答案 2 :(得分:1)

虽然Rufu's Answer resolve the problem并未解释问题存在的原因。

存在此问题是因为您的财产:

public IArbitraryQualifier ArbitraryQualifier { get; }

名称与您的具体课程相同:

public class ArbitraryQualifier

由于代码包含在Person类中,因此编译器会将名称解析为(local =此)本地范围的变量(var ...等),然后是Local Fields / Properties,然后是Accessible Named类在当前名称空间中,然后在名称空间链中向上。

重命名本地/此类的属性名称也可以解决此问题。

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;
        }
    }
}