如何实现虚拟静态属性?(How to implement virtual static proper

2019-07-21 08:48发布

据我所知, C#不支持虚拟静态属性。 如何实现这样的行为C#

我想归档基类的所有派生类必须重写的静态属性。 获取派生类型,我想访问一个静态属性称为Identifier

Type t = typeof(DerivedClass);
var identifier= (String) t.GetProperty("Identifier", BindingFlags.Static).GetValue(null, null);

Answer 1:

因为你还没有五年左右的accpted答案后,让我试试看(再次)..

我曾想过, 奇异递归模板模式作为一种解决方法,但因为你打开BaseClass继承它不会是一个好主意。 你可能想看看利珀特先生的博文以更好地理解为什么。

  • 方案1:您没有注册,我不认识..

     public abstract class BaseClass { protected static void Register<U>(String identifier) where U : BaseClass { m_identities.Add(typeof(U).GetHashCode(), identifier); } public static String GetIdentifier<U>() where U : BaseClass { var t = typeof(U); var identifier = default(String); RuntimeHelpers.RunClassConstructor(t.TypeHandle); m_identities.TryGetValue(t.GetHashCode(), out identifier); return identifier; } static Dictionary<int, String> m_identities = new Dictionary<int, String> { }; } public class DerivedClassA:BaseClass { static DerivedClassA() { BaseClass.Register<DerivedClassA>("12dc2490-065d-449e-a199-6ba051c93622"); } } public class DerivedClassB:BaseClass { static DerivedClassB() { BaseClass.Register<DerivedClassB>("9745e24a-c38b-417d-a44d-0717e10e3b96"); } } 

    测试:

     Debug.Print("{0}", BaseClass.GetIdentifier<DerivedClassA>()); Debug.Print("{0}", BaseClass.GetIdentifier<DerivedClassB>()); 

这是是通过类型初始化一个相对简单的图案。 的Register方法仅暴露于派生类; 和两者GetIdentifierRegister方法被限制为与从派生的类型参数调用BaseClass 。 虽然我们不强制派生类覆盖任何东西,如果不注册本身, GetIdentifier不能识别它,并返回null

  • 解决方法2:在你显示你的身份,你买一个默认值。 谁你以为你是,我相信 - 只要没有歧义。

     public abstract class BaseClass { public abstract String Identifier { get; } public static Type GetDerivedClass(String identifier) { return m_aliases[identifier]; } public static String GetIdentifier(Type t) { var value = default(String); if(t.IsSubclassOf(typeof(BaseClass))) { var key = t.GetHashCode(); if(!m_identities.TryGetValue(key, out value)) { value=""+key; m_aliases.Add(value, t); m_identities[key]=value; } } return value; } static void UpdateAlias(BaseClass x) { var t = x.GetType(); var value = x.Identifier; m_aliases.Add(value, t); m_identities[t.GetHashCode()]=value; } protected BaseClass() { BaseClass.UpdateAlias(this); } static Dictionary<String, Type> m_aliases = new Dictionary<String, Type> { }; static Dictionary<int, String> m_identities = new Dictionary<int, String> { }; } 

     public class DerivedClassA:BaseClass { public override String Identifier { get { return "just text"; } } } public class DerivedClassB:BaseClass { public override String Identifier { get { return "just text"; } } } 

    和测试:

     public static void TestMethod() { var idBeforeInstantiation = BaseClass.GetIdentifier(typeof(DerivedClassA)); var y = new DerivedClassA { }; var idAfterInstantiation = BaseClass.GetIdentifier(typeof(DerivedClassA)); Debug.Print("B's: {0}", BaseClass.GetIdentifier(typeof(DerivedClassB))); Debug.Print("A's after: {0}", idAfterInstantiation); Debug.Print("A's before: {0}", idBeforeInstantiation); Debug.Print("A's present: {0}", BaseClass.GetIdentifier(typeof(DerivedClassA))); var type1 = BaseClass.GetDerivedClass(idAfterInstantiation); var type2 = BaseClass.GetDerivedClass(idBeforeInstantiation); Debug.Print("{0}", type2==type1); // true Debug.Print("{0}", type2==typeof(DerivedClassA)); // true Debug.Print("{0}", type1==typeof(DerivedClassA)); // true var typeB=BaseClass.GetDerivedClass(BaseClass.GetIdentifier(typeof(DerivedClassB))); var x = new DerivedClassB { }; // confilct } 

显然,这是一个更复杂的解决方案。 正如你所看到idBeforeInstantiationidAfterInstantiation是不同的,但是,它们要么是有效标识符DerivedClassAm_identities包含每个派生类,最后更新标识m_aliases将包含所有派生类标识符别名。 由于虚拟静态相结合是不是语言的功能目前(也许永远..),如果我们要执行覆盖那么我们通过一些变通方法来做到这一点。 如果你选择溶液2,您可能要implemenet你自己UpdateAlias防止提供太多不同的化名为单一类型的,但他们都将是有效的派生类。 在测试的最后一条语句放在刻意证明标识符的冲突。

对于这两种解决方案都经过精心设计为您考虑的不实例化派生类,他们没有要求



Answer 2:

简而言之,你不能,所以我冒昧地建议你把它和尝试别的东西。

请参阅在回答这个SO发布。 如果你实现这样的功能,您将有严重的问题,继承。

去过也做过。 之后,我又来到了我的感觉,我去了一个普通的继承方法。 我想你也许应该这样做。



Answer 3:

要做到这一点的另一种方式,不需要一个类被注册,但确实需要一些额外的工作是创建一个拥有“静态”数据,每个派生类类型的静态类,并从静态返回一个常量/静态值类。 让我来解释一下这种方法的细节。

一个很大的原因有静态属性,始终是为类的每个成员同样是为了避免不必要的内存使用和重复。 尽管该方法证明这里不避免这种情况完全是,它仍然绕过大部分的“额外”开销。 唯一的使用情况下面的例子将不能满足是,如果使用一个静态属性的原因是为了让你不必有一个实例,因为你必须有一个实例来获取数据。

如果你需要一个虚拟的字段或属性,始终是对的类(静态),每个成员一样,使用返回这样的“常量”或静态数据的非静态属性:

public static class MyStaticData
{
    public static const string Class1String = "MyString1";
    public static const int Class1Int = 1;
    public static const string Class2String = "MyString2";
    public static const int Class2Int = 2;
    // etc...
}

public abstract class MyBaseClass
{
    public abstract string MyPseudoVirtualStringProperty { get; }
    public abstract int MyPseudoVirtualIntProperty { get; }
}

public class MyDerivedClass1 : My BaseClass
{
    public override string MyPseudoVirtualStringProperty { get { return MyStaticData.Class1String; } }
    public override int MyPseudoVirtualIntProperty { get { return MyStaticData.Class1Int } }
}

public class MyDerivedClass2 : My BaseClass
{
    public override string MyPseudoVirtualStringProperty { get { return MyStaticData.Class2String; } }
    public override int MyPseudoVirtualIntProperty { get { return MyStaticData.Class2Int } }
}


文章来源: How to implement virtual static properties?