据我所知, C#
不支持虚拟静态属性。 如何实现这样的行为C#
我想归档基类的所有派生类必须重写的静态属性。 获取派生类型,我想访问一个静态属性称为Identifier
Type t = typeof(DerivedClass);
var identifier= (String) t.GetProperty("Identifier", BindingFlags.Static).GetValue(null, null);
据我所知, C#
不支持虚拟静态属性。 如何实现这样的行为C#
我想归档基类的所有派生类必须重写的静态属性。 获取派生类型,我想访问一个静态属性称为Identifier
Type t = typeof(DerivedClass);
var identifier= (String) t.GetProperty("Identifier", BindingFlags.Static).GetValue(null, null);
因为你还没有五年左右的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
方法仅暴露于派生类; 和两者GetIdentifier
和Register
方法被限制为与从派生的类型参数调用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 }
显然,这是一个更复杂的解决方案。 正如你所看到idBeforeInstantiation
和idAfterInstantiation
是不同的,但是,它们要么是有效标识符DerivedClassA
。 m_identities
包含每个派生类,最后更新标识m_aliases
将包含所有派生类标识符别名。 由于虚拟和静态相结合是不是语言的功能目前(也许永远..),如果我们要执行覆盖那么我们通过一些变通方法来做到这一点。 如果你选择溶液2,您可能要implemenet你自己UpdateAlias
防止提供太多不同的化名为单一类型的,但他们都将是有效的派生类。 在测试的最后一条语句放在刻意证明标识符的冲突。
对于这两种解决方案都经过精心设计为您考虑的不实例化派生类,他们没有要求 。
简而言之,你不能,所以我冒昧地建议你把它和尝试别的东西。
请参阅在回答这个SO发布。 如果你能实现这样的功能,您将有严重的问题,继承。
去过也做过。 之后,我又来到了我的感觉,我去了一个普通的继承方法。 我想你也许应该这样做。
要做到这一点的另一种方式,不需要一个类被注册,但确实需要一些额外的工作是创建一个拥有“静态”数据,每个派生类类型的静态类,并从静态返回一个常量/静态值类。 让我来解释一下这种方法的细节。
一个很大的原因有静态属性,始终是为类的每个成员同样是为了避免不必要的内存使用和重复。 尽管该方法证明这里不避免这种情况完全是,它仍然绕过大部分的“额外”开销。 唯一的使用情况下面的例子将不能满足是,如果使用一个静态属性的原因是为了让你不必有一个实例,因为你必须有一个实例来获取数据。
如果你需要一个虚拟的字段或属性,始终是对的类(静态),每个成员一样,使用返回这样的“常量”或静态数据的非静态属性:
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 } }
}