#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, но это не одно и то же. Это добавит некоторую сложность.