Пользовательский тип в C # (похож на typescript)

#c# #typescript

#c# #typescript

Вопрос:

В typescript я могу определить тип как строку или массив строк, подобный этому

 type MyStringType = string | string[]
  

Могу ли я сделать что-то подобное в C #?

Комментарии:

1. Нет. Может быть, расскажите нам о практической проблеме, которую вы пытаетесь решить?

2. Это называется «различаемое объединение». В C # (по крайней мере, в настоящее время) нет встроенной языковой функции, но при поиске вы найдете несколько реализаций.

3. @sweeper Я отправляю значения фильтра таблицы обратно на сервер. Обычно это одна строка для фильтрации по равным, содержит, начинается с и т.д. При фильтрации ПО IN (является членом списка) Мне нужен массив строк

4. в вашем явном случае вы могли бы рассмотреть возможность использования ключевого слова params , ваша реализация также должна была бы работать с коллекцией (иногда только с одним элементом), но у вашего вызывающего абонента есть выбор очень легко передать 1 или более строк. Это, безусловно, не связано с разделенными объединениями и приведенным вами примером typescript, но это может помочь с вашей конкретной проблемой в C#

Ответ №1:

В C # нет функции для типов объединения. Есть несколько предложений, но я не думаю, что они планируются в ближайшее время.

С учетом сказанного, вы можете реализовать свой пользовательский тип оболочки и преобразовать входные данные в этот тип перед их использованием.

 struct Union<T1, T2>
{
    public T1 Left { get; } 
    public T2 Right { get; } 

    public bool IsLeft => !IsRight;
    public bool IsRight { get; } 

    public Union(T1 left) => (Left, Right, IsRight) = (left, default, false);
    public Union(T2 right) => (Left, Right, IsRight) = (default, right, true);

    public static implicit operator Union<T1, T2>(T1 left) => new Union<T1, T2>(left);
    public static implicit operator Union<T1, T2>(T2 right) => new Union<T1, T2>(right);
}
  

Благодаря неявным преобразованиям вы можете использовать значение любого из вариантов, где требуется объединение. Итак, оба они работают:

 void Foo(Union<string, string[]> val){} 

Foo("str") 
Foo(new string[] {"str1", "str2"});
  

Обратите внимание, что это не реализация производственного уровня. Вы, вероятно, хотите переопределить Equals , возможно, выбросить, InvalidOperarionException если кто-то обращается, Left когда IsLeft есть false , и наоборот.

Фактическая реализация, поддерживаемая языком, потребовала бы меньше накладных расходов (возможно, повторное использование одного поля размера max(sizeof(T1), sizeof(T2))) , но, увы, это работает ™ и строго типизировано.

Комментарии:

1. Спасибо @V0ldek, это может улучшить трюк. Не так красиво, как версия typescript, но это ошибка C #.

Ответ №2:

Нет, вы не можете. C # — это строго типизированный язык, который (пока) не позволяет объявлять переменную нескольких типов.

Есть возможность использовать dynamic ключевое слово: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic

Тип является статическим типом, но объект типа dynamic обходит статическую проверку типа. В большинстве случаев он функционирует так, как будто имеет тип object. Предполагается, что во время компиляции элемент, который вводится как динамический, поддерживает любую операцию. Поэтому вам не нужно беспокоиться о том, получает ли объект свое значение из COM API, из динамического языка, такого как IronPython, из объектной модели документа HTML (DOM), из отражения или откуда-либо еще в программе. Однако, если код не является достоверным

Фактически его можно использовать как any тип в typescript, но это не рекомендуется из-за возможных ошибок во время выполнения.

Комментарии:

1. Я думал об этом, но я хочу иметь проверку типов. Возможно, мне просто нужно иметь 2 свойства в моем классе, string stringValue и string[] StringArrayValue.

2. Просто обратите внимание, что строгая типизация не имеет ничего общего с разрешением типов объединения в вашем языке. Просто C # не поддерживает эту функцию ( по крайней мере, пока ).

3. Вы можете использовать что-то вроде oneOf, но это не одно и то же. Это добавит некоторую сложность.