【问题标题】:C# Semi-static semi-abstract variableC# 半静态半抽象变量
【发布时间】:2016-11-19 08:32:14
【问题描述】:

很难给它起个标题,如果你能想到一个更好的,我会更新它。但我正在寻找的是一种能够从实例对象引用静态值的方法。例如,假设您有一个名为Animal 的抽象类和两个名为CatDog 的子类。在抽象类上,我想要一个名为GenusSpecies 的实例变量,当然,这在动物级别没有值,因为它是一个抽象类,但每个Cat 都会有相同的值,但它会与所有的 Dogs 不同。但是,我希望 CatDog 类对每种类型的实例都有一个静态值,但我不想在每个实例上都设置它的值,但我希望能够像实例变量一样引用它,因为我将拥有一个像这样的通用变量。

Animal a = new Cat("Garfield");

但我期待

a.GenusSpecies == "Felis catus"

但我不想写 GenusSpecies = "Felis catus"; 在构造函数中。但是,如果能够引用 Cat.GenusSpecies 静态值也将是一件好事,因为 Cat 类型的每个实例总是相同的。我知道在某些时候我正在划分两种引用它的方式之间的差异,但是有什么方法可以同时实现这两种引用类型?我希望我已经正确解释了这一点。

【问题讨论】:

  • 您可能想要创建一个带有属名的自定义属性并用它标记每个类,例如[GenusAttribute("Felis catus")]
  • 确实,这是一个有效且非常好的问题。我会用基于执行上下文或基于引用的分组半静态属性来扩展它。例如,我们需要创建六个团队,每个团队应该有五个 ID 为 1...5 的用户。 ID 属于用户,但在团队级别必须是唯一的!在这种情况下,我将在团队级别使用半静态 LastId OR IDsInUse 但出于某种原因我希望在用户处看到实现。

标签: c# inheritance static instance abstract


【解决方案1】:
public class GenusAttribute : Attribute
{
    public string GenusName {get; private set;}
    public GenusAttribute(string genusName)
    {
        GenusName = genusName;
    }
}

[GenusAttribute("Catus")] // or simply [Genus("Catus")], no need to type 'Attribute' in here
public class Cat : Animal
{

}

【讨论】:

  • OP 想要它,以便他可以同时访问 Cat.GenusSpeciessomeObjectOfTypeAnimal.GenusSpecies。你的代码怎么能做到这一点?我对属性不是很熟悉(可能OP也不是)。你能解释一下如何通过这两种方式访问​​GenusSpecies吗?
  • 最好的方式是实现虚拟或抽象方法(取决于Animal 基类是否有自己的属),如virtual string GetGenus()。然后返回此处为 eaxmple 描述的属性:msdn.microsoft.com/en-us/library/71s1zwct(v=vs.110).aspx
【解决方案2】:

我现在正在打电话,所以我不确定这段代码是否可以工作,但你的基类不能有一个调用静态属性的实例属性。

abstract class Base
{
    public abstract static string Value { get; }

    public abstract string InstanceValue { get { return Value; } }
}

当我可以在我的电脑上测试这是否可行时,我会回来检查一下。

【讨论】:

    【解决方案3】:

    通过这里给出的一些建议,我想出了一个解决方案,尽管与我最初希望的有所不同。在创建新子类时,我一直在寻找开销最少的解决方案,并且还想要一个感觉不是完整的 hack 或者只是比我正在寻找的更冗长的代码的解决方案。所以我找到了一个解决方案,我创建了两个类似于 TheLethalCoder 解决方案的变量。

    public abstract class Animal
    {
        public static string GENUSSPECIES;
        public abstract string GenusSpecies { get; }
    
        public string Name;
    
        public Animal(string name)
        {
            Name = name;
        }
    }
    

    public class Cat : Animal
    {
        public static new string GENUSSPECIES = "Felis Catus"; 
    
        public Cat(string name) : base(name) { }
    
        public override string GenusSpecies
        {
            get { return Cat.GENUSSPECIES; }
        }
    }
    

    起初,我试图从一个实例变量中访问一个静态值,我认为这应该是可能的,但是,它只是在这种语言中不可用。因此,我做了下一件最好的事情,并将真实值存储为静态值,因为它永远不会改变,但我创建了一个单独的实例属性来返回该静态值。添加新子类时很容易维护,只是有点愚蠢,我必须根据我想要从中访问值的范围来不同地引用它们。

    【讨论】:

      【解决方案4】:

      您可以将GenusSpecies 声明为Animal 中的(只读)字符串字段,并添加一个构造函数,该构造函数将根据实际实例化的Type 设置其值:

      public abstract class Animal
      {
          public readonly string GenusSpecies;
          public string Name { get; set; }
      
          public Animal(string name)
          {
              Name = name;
      
              if (this is Dog)
                  GenusSpecies = "Canis";
              else if (this is Cat)
                  GenusSpecies = "Felis catus";
          }
      }
      
      public class Dog: Animal
      {
          public Dog(string name): base(name)
          {
      
          }
      }
      
      class Cat : Animal
      {
          public Cat(string name): base(name)
          {
      
          }
      }
      

      这样在您的Main 代码中您将拥有:

      class Program
      {
      
          static void Main(string[] args)
          {
      
              Dog myDog = new Dog("myDog");
              Cat myCat = new Cat("myCat");
              Animal a = new Cat("Garfield");
      
              Console.WriteLine("Dog {0} has GenusSpecies:{1}", myDog.Name, myDog.GenusSpecies);
              Console.WriteLine("Cat {0} has GenusSpecies:{1}", myCat.Name, myCat.GenusSpecies);
              Console.WriteLine("Animal {0} has GenusSpecies:{1}", a.Name, a.GenusSpecies);
      
          }
      }
      

      【讨论】:

      • 我希望勇敢的反对者解释他投票的原因,并让我提高我的回答,其他人也学习。
      • 您从未解决过从静态角度引用 this 的问题(也就是不创建实例),我还特别要求提供一种解决方案,在构造函数中不包含此值的分配。跨度>
      猜你喜欢
      • 2011-08-12
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      • 2012-01-02
      • 2011-07-27
      • 1970-01-01
      相关资源
      最近更新 更多