Можно ли вызвать метод статического абстрактного интерфейса из реализации другого метода статического интерфейса?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Можно ли вызвать метод статического абстрактного интерфейса из реализации другого метода статического интерфейса?

Сообщение Anonymous »

Вопрос просто в комментарии к коду ниже
Кстати, этот код действителен только для версии языка C#-11
(т. е.: создайте проект платформы Net 8.0 или более поздней версии для тестирования).
Не является ли проблема кода ниже ограничения нового синтаксиса C#
(что было бы печально, потому что этот вариант использования, я думаю, один из самых востребованных)?
Или я ошибаюсь в синтаксисе ?
Моя цель — использовать позже «IDynamicEnum» для типа, известного только во время выполнения (с использованием отражения). Но я не уверен, предназначен ли метод статического интерфейса для использования, как я пытаюсь сделать здесь, или он предназначен только для случая, когда T всегда известен во время компиляции. я просто играю с C# 11.
Я знаю, что могу полностью удалить интерфейс IDynamicEnum и использовать что-то вроде typeof(IDynamicEnum).MakeGenericType(the_type_is_got_by_reflection), но этот вопрос кажется интересным в любом случае.
/// Tag a class that acts as an enum class (in the java way)

public interface IDynamicEnum
{
string Name { get; }
ulong Value { get; }

static abstract IEnumerable GetAllValues();
}

///
public interface IDynamicEnum : IDynamicEnum
where T : class, IDynamicEnum
{
// A better signature: We strongly type
new static abstract IEnumerable GetAllValues();

// I would like to automatically implement the non generic method...
// To do that, intuitively i would like to write this line
// which is kind of a "return type covariance on static interface method"
// But sadly it gives error CS8926
//static IEnumerable IDynamicEnum.GetAllValues() => GetAllValues();
}

public class MyDynamicEnum : IDynamicEnum
{
public string Name { get; }
public ulong Value { get; }

public static MyDynamicEnum Foo { get; } = new MyDynamicEnum("Foo", 1);
public static MyDynamicEnum Bar { get; } = new MyDynamicEnum("Bar", 2);
public static MyDynamicEnum Baz { get; } = new MyDynamicEnum("Baz", 3);

public static IEnumerable AllValues { get; } = new[] { Foo, Bar, Baz };

protected MyDynamicEnum(string name, long value) { Name = name; Value = value; }

public static IEnumerable GetAllValues() => AllValues;

// So I could get rid of this annoying / duplicated line
static IEnumerable IDynamicEnum.GetAllValues() => AllValues;
}

РЕДАКТИРОВАТЬ: продолжайте читать, только если вам недостаточно абстрактного вопроса, приведенного выше.
Настоящее приложение предназначено для доброты о перечислении неизвестно заранее, например, для обработки всего крошечного набора значений, связанных с анализом файлов csproj/sln:
  • Конфигурация («Отладка», « Release", пользовательские, определенные пользователями... нет возможности узнать их в заранее)
  • Платформы («x86», x64, «Любой ЦП», последняя как много разных написаний, с пространством, с «ЦП» или «ЦП»)
  • li>
    Рамка: содержит множество различных значений. Стандартные (которые я хочу обработать): «net48», ..., «net8.0», а также много необычных/. редкое значение, которое я не хочу обрабатывать, например "net7.0-tvos". У них тоже много чего можно написать (с точкой или без...)
Чтобы было "правильно" алгоритмов, лучше иметь способ их идентифицировать, не обрабатывая каждый раз всю их форму записи. На самом деле это скорее шаблон Flyweigh, чем концепция динамического перечисления. В любом случае, если пользователь хочет расширить тип DynamicEnum, добавив поддержку «net7.0-android» и создать статический экземпляр Singleton в своем коде, чтобы ссылаться на него с помощью своего алгоритма, мой код не должен мешать ему сделать это
Итак… ок, имя «DynamicEnum», возможно, неправильное. но я хотел задать простой вопрос, а не вступать в дискуссию о проблеме XY.
Более того, я хочу, чтобы этот код работал как в net48, так и в net8.0, поэтому я воспользуюсь преимуществами компилятора. потому что он проверит компиляцию кода для bioth net8.0 и net4.8. Таким образом, ограничение статического метода дает мне больше вероятности, метод также существует для net48 (я не знаю, нет гарантии, но больше, чем если бы разработчик ожидал, что прочтет XML-документ...)
Мой текущий решение выглядит так:
// comment for stackoverflow: this interface looks simple / intuitive
public interface IDynamicEnum
{
/// Represent the culture invariant technical representation name
string NormalizedName { get; }

/// The value of the enum (if supported, see MaxValueRepresentation)
ulong Value { get; }
}

// comment for stackoverflow: This interface adds "behavior" allowed by new C# 11 syntax
public interface IDynamicEnum : IDynamicEnum
where T : class, IDynamicEnum
{
#if NET8_0_OR_GREATER

static abstract ulong? MaxValueRepresentation { get; }
static abstract IEnumerable GetAllValues();

// Is it not possible to write something like this (that does not cause a CS8926 error) ?
//static IEnumerable IDynamicEnum.GetAllValues() => GetAllValues();
#endif

}

// comment for stackoverflow: this interface is the helper class that works both for net48/net8.0
public static class IDynamicEnum_Extensions
{
#if NET8_0_OR_GREATER
public static IEnumerable GetAllValues()
where T: class, IDynamicEnum
{
return T.GetAllValues();
}
#else
public static IEnumerable GetAllValues()
where T : class, IDynamicEnum
=> (IEnumerable)_GetAllValues(typeof(T));
#endif

public static IEnumerable GetAllValues(Type dynamicEnumType)
{
var interfaceType = typeof(IDynamicEnum).MakeGenericType(dynamicEnumType);
if (!interfaceType.IsAssignableFrom(dynamicEnumType))
throw new ArgumentException($"Type {dynamicEnumType} is not implementing {interfaceType}", nameof(dynamicEnumType));
return (IEnumerable < IDynamicEnum > )_GetAllValues(dynamicEnumType);
}
static IEnumerable _GetAllValues(Type type)
{
var m = type.GetMethod("GetAllValues", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var enumerable = m.Invoke(null, null);
return (IEnumerable)enumerable;
}
}

// comment for stackoverflow: Now a class implementing it, note there is no more "#if NET80..." line here:

[DebuggerDisplay("{" + nameof(DisplayName) + ",nq}")]
public class eConfig : IDynamicEnum
{
public static eConfig Debug { get; } = new eConfig("Debug");
public static eConfig Release { get; } = new eConfig("Release");
public string DisplayName { get; }

/// Name of platform lowercased no duplicate space, trimmed
public string NormalizedName { get; }

///
/// Open constructor to add custom / weird config as static public property in a child class.
///
protected eConfig(string displayName, string normalizedName = null)
{
DisplayName = displayName;
NormalizedName = Normalize(normalizedName ?? displayName);
_AllStandardConfigurations = _AllStandardConfigurations ?? new();
_byNormalizedNames = _byNormalizedNames ?? new();

if (null == TryGetByNormalizedName(NormalizedName))
{
_byNormalizedNames.Add(NormalizedName, this);
_AllStandardConfigurations.Add(this);
}
}

public override string ToString()
{
return DisplayName;
}

public static IReadOnlyCollection AllStandardConfigurations => _AllStandardConfigurations;
static List _AllStandardConfigurations;
static Dictionary _byNormalizedNames;

public static eConfig GetByNormalizedName(string name)
{
return TryGetByNormalizedName(name)
?? throw new TechnicalException($"{name} not recognized as a valid configuration (or not yet handled, use constructor for that!)");
}
public static eConfig TryGetByNormalizedName(string name)
{
if (_byNormalizedNames.TryGetValue(Normalize(name), out var result))
return result;
return null;
}

static string Normalize(string name)
{
while (name.Contains(" "))
name = name.Replace(" ", " ");
return name.Trim().ToLowerInvariant();
}

public static IEnumerable GetAllValues() => _byNormalizedNames.Values;
public static ulong? MaxValueRepresentation => null;
string IDynamicEnum.NormalizedName => NormalizedName;
ulong IDynamicEnum.Value => throw new NotSupportedException();
}


Подробнее здесь: https://stackoverflow.com/questions/793 ... ntation-of
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»