需要像C#中的静态继承之类的东西

时间:2011-05-07 15:30:21

标签: c# inheritance static

我有一个小设计问题,想咨询。 假设我们有以下类层次结构:

abstract class A
{
}

class B : A
{
}

class C: A
{
}

我希望B和C都有一个特定的字段x,这样它的值在各个类之间是不同的,但在同一个类的所有实例之间共享(即:如果b1,b2是B和c1的实例,c2实例是C然后b1.x = b2.x和c1.x = c2.x和b1.x!= c1.x)。 有没有一种优雅的方法来利用B,C派生自相同的基类或者我必须在两个类中创建静态字段x这一事实?

提前致谢。

7 个答案:

答案 0 :(得分:4)

你的意思是这样吗?

abstract class A
{
    static Dictionary<Type, int> all_x;
    protected int X {
        get { return all_x[GetType()]; }
        set { all_x[GetType()] = value; }
    }
}

如果必须是一个字段,那么你可以通过引用传递:

abstract class A
{
    class SharedType { int x; }
    static Dictionary<Type, SharedType> all_shared;
    protected SharedType Shared {
        get
        {
            Type t = GetType();
            SharedType result;
            if (!all_shared.TryGetValue(t, out result) {
                 result = new SharedType();
                 all_shared.Add(t, result);
            }
            return result;
        }
    }
}

此外,我们可以通过每个实例只执行一次查询来提高性能:

abstract class A
{
    class SharedType { int x; }
    static Dictionary<Type, SharedType> all_shared;
    protected SharedType Shared;
    A() {
        Type t = GetType();
        if (!all_shared.TryGetValue(t, out Shared) {
             Shared = new SharedType();
             all_shared.Add(t, Shared);
        }
    }
}

答案 1 :(得分:0)

我知道这样做的唯一方法是将类A作为泛型类,即类A<T>。然后让B类为泛型类型实现与C类实现的泛型类型不同的类型。

如果你不使用泛型,那么我相信这在.NET中是不可能的。

这是一个例子,让我们说你感兴趣的值是一个数据结构,成员是int Foo和string Bar。一个派生类可以实现与另一个相同的结构(但是派生类型不同) - 两个结构将实现相同的接口。

interface IAvalue
    {
        int Foo { get; set;}
        string Bar {get; set;}
    }

    struct BValue
        : IAvalue
    {

        public int Foo { get; set; }
        public string Bar { get; set; }
    }

    struct CValue
        : IAvalue
    {
        public int Foo { get; set; }
        public string Bar { get; set; }


    }

    abstract class A<T> where T : IAvalue
    {
        protected static T myValue;
    }

    class B : A<BValue>
    {
        static B()
        {
            myValue.Foo = 1;
            myValue.Bar = "text1";
        }
    }

    class C : A<CValue>
    {
        static C()
        {
            myValue.Foo = 2;
            myValue.Bar = "text2";
        }
    }

答案 2 :(得分:0)

这些值对于字段x应该是什么?如果你需要指定A的x值应为“a”,则B的x值应为“b”等,那么你必须指定值“a”,“b”,..某处,然后你也可以使用:

abstract class A {
    public static int x = 1;    // Just using "int" as example.
}

class B : A {
    public static int x = 2;
}

如果您不关心值是什么(那时您需要哪种类型)但只是希望值“不同”,那么您可以使用以下内容来代替使用字段:

abstract class A {
    public int X { get { return this.GetType().GetHashCode(); } }
}

这不会考虑哈希冲突,但也许它有用吗?

你想要实现的目标是什么?

答案 3 :(得分:0)

以Ben Voigt的第一个答案为基础,我认为您对基类的要求是:

public abstract class A
    {
        private static ConcurrentDictionary<Type, int> _typeIDs = new ConcurrentDictionary<Type, int>();
        private static int _nextID = 1;

        public int TypeID
        {
            get
            {
                return _typeIDs.GetOrAdd(this.GetType(), type => System.Threading.Interlocked.Increment(ref _nextID));
            }
        }
    }

答案 4 :(得分:0)

public abstract class A
{
    public abstract int Value { get; }
}

public class B : A
{
    public override int Value { get { return 1; } }
}

public class C : A
{
    public override int Value { get { return 2; } }
}

答案 5 :(得分:0)

您可以使用一个.net功能:如果您在泛型类中有静态数据成员,.net会为您使用的每种泛型类型创建不同的静态数据成员实例。

所以,你可以写:

public abstract class A<T> where T : A<T>
{
    protected static int myVariable { get; set; }
}

继承你的课程:

public class B : A<B>
{
    public B()
    {
        myVariable = 1;
    }
    public int GetVariable()
    {
        return myVariable;
    }
}

public class C : A<C>
{
    public C()
    {
        myVariable = 2;
    }
    public int GetVariable()
    {
        return myVariable;
    }
}

然后,B的每个实例都将拥有对myVariable的一个实例的共享访问权限,并且C的每个实例都将拥有对另一个实例的共享权限。

因此,如果您添加Set(int a)方法:

public void Set(int a)
{
    myVariable = a;
}

并运行以下代码:

static void Main(string[] args)
{
    B b1 = new B();
    C c1 = new C();
    B b2 = new B();
    C c2 = new C();

    Console.Write("{0}; ", b1.GetVariable());  // 1
    Console.Write("{0}; ", b2.GetVariable());  // 1
    Console.Write("{0}; ", c1.GetVariable());  // 2
    Console.Write("{0}; ", c2.GetVariable());  // 2

    Console.WriteLine();

    c2.Set(333);

    Console.Write("{0}; ", b1.GetVariable());  // 1
    Console.Write("{0}; ", b2.GetVariable());  // 1
    Console.Write("{0}; ", c1.GetVariable());  // 333
    Console.Write("{0}; ", c2.GetVariable());  // 333

    Console.ReadLine();
}

你得到:1; 1; 2; 2; 1; 1; 333; 333;输出。

答案 6 :(得分:0)

我建议定义一个静态字典&lt; Type,Integer []&gt;,让基类构造函数自己调用GetType(),看看它是否还在静态字典中。如果没有,请创建一个新的单元素数组并将其存储在字典中。否则从字典中获取数组并将其存储在实例字段中。然后定义一个读取或写入数组元素零的属性。这种方法将实现所有类的衍生物和子衍生物所要求的语义。