Для вас до сих пор нет ответа на вопрос о accpted пять лет спустя, позвольте мне дать ему попробовать (снова) ..
я когда-либо думали о Curiously Recurring Template Pattern как обходной путь, но так как вы» ll открыть BaseClass
для наследования это не будет хорошей идеей. Возможно, вы захотите взглянуть на Mr. Lippert's blogpost, чтобы лучше понять, почему.
Решение 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
будет содержать все псевдонимы идентификатора для производных классов. Так как комбинация virtual и static не является признаком данного языка (возможно, никогда ..), если мы хотим обеспечить отмену переопределения, тогда мы должны сделать это через некоторое обходное решение. Если вы выберете решение2, вы можете захотеть реализовать свой собственный UpdateAlias
, чтобы не допустить, чтобы производные классы предоставляли слишком много различных псевдонимов для одного типа, хотя все они будут действительны. Последнее утверждение в тесте преднамеренно демонстрирует конфликт идентификаторов.
Для этих двух решений тщательно разработаны для рассмотрения не создать экземпляр производные классов, ни один из них не требует что.
Статические члены не могут быть переопределены (или это «переопределено»?) Pardon my bad english = ( –
Как вы сказали, C# не поддерживает его, поэтому вы не можете его реализовать. – Servy
В любом случае, для чего вы хотите это сделать? такое же может быть достигнуто с помощью 'Attributes'. –