Есть ли в C # эквивалент typedef или как-то похожее поведение? Я немного погуглил, но везде я выгляжу негативно. В настоящее время у меня есть ситуация, похожая на следующую:
class GenericClass<T>
{
public event EventHandler<EventData> MyEvent;
public class EventData : EventArgs { /* snip */ }
// ... snip
}
Теперь не нужно быть ученым-ракетчиком, чтобы понять, что это может очень быстро привести к значительным наборам (извинения за ужасный каламбур) при попытке реализовать обработчик для этого события. В конечном итоге это будет примерно так:
GenericClass<int> gcInt = new GenericClass<int>;
gcInt.MyEvent += new EventHandler<GenericClass<int>.EventData>(gcInt_MyEvent);
// ...
private void gcInt_MyEvent(object sender, GenericClass<int>.EventData e)
{
throw new NotImplementedException();
}
За исключением того, что в моем случае я уже использовал сложный тип, а не просто int. Было бы хорошо, если бы можно было немного упростить это ...
Редактировать: т.е. возможно, определите EventHandler вместо необходимости переопределять его, чтобы получить похожее поведение.
using MyClassDictionary = System.Collections.Generic.Dictionary<System.String, MyNamespace.MyClass>;
это правильно? В противном случае он, кажется, не учитываетusing
определения над ним.typedef uint8 myuuid[16];
с помощью директивы using.using myuuid = Byte[16];
не компилируетсяusing
может использоваться только для создания псевдонимов типов .typedef
кажется гораздо более гибким, поскольку он может создать псевдоним для всего объявления (включая размеры массива). Есть ли альтернатива в этом случае?Джон действительно дал хорошее решение, я не знал, что ты сможешь это сделать!
Временами я прибегал к наследованию от класса и созданию его конструкторов. Например
Не лучшее решение (если ваша сборка не используется другими людьми), но оно работает.
источник
public class FooList : LikeType<IReadOnlyList<Foo>> { ... }
а затем использовать его в любом месте вы бы ожидатьIReadOnlyList<Foo>
. Мой ответ ниже показывает больше деталей.Foo
если передан, например, шаблонному методу, который принимаетList<T>
. При правильном typedef это было бы возможно.Если вы знаете, что делаете, вы можете определить класс с неявными операторами для преобразования между классом псевдонима и реальным классом.
Я на самом деле не одобряю это и никогда не использовал что-то подобное, но это могло бы сработать для некоторых конкретных обстоятельств.
источник
C # поддерживает некоторую унаследованную ковариацию для делегатов событий, поэтому такой метод:
Может быть использован для подписки на ваше событие, не требуется явное приведение
Вы даже можете использовать лямбда-синтаксис, и intellisense все будет сделано для вас:
источник
Я думаю, что нет typedef. Вы можете определить только определенный тип делегата вместо общего в GenericClass, т.е.
Это сделало бы это короче. Но как насчет следующего предложения:
Используйте Visual Studio. Таким образом, когда вы набрали
он уже предоставляет полную подпись обработчика событий от Intellisense. Нажмите клавишу TAB, и она там. Примите имя сгенерированного обработчика или измените его, а затем снова нажмите клавишу TAB, чтобы автоматически сгенерировать заглушку обработчика.
источник
И в C ++, и в C # отсутствуют простые способы создания нового типа, который семантически идентичен существующему типу. Я нахожу такие 'typedefs' совершенно необходимыми для безопасного программирования типов, и это настоящий позор, что c # не имеет их встроенных. Разница между
void f(string connectionID, string username)
доvoid f(ConID connectionID, UserName username)
очевидна ...(Вы можете добиться чего-то подобного в C ++ с помощью boost в BOOST_STRONG_TYPEDEF)
Может быть заманчиво использовать наследование, но это имеет некоторые серьезные ограничения:
Единственный способ добиться подобного в C # - это создать наш тип в новом классе:
Хотя это сработает, это очень многословно только для typedef. Кроме того, у нас есть проблема с сериализацией (то есть с Json), поскольку мы хотим сериализовать класс через его свойство Composed.
Ниже приведен вспомогательный класс, который использует «шаблон любопытно повторяющегося шаблона», чтобы сделать это намного проще:
С Composer вышеупомянутый класс становится просто:
Кроме того, он
SomeTypeTypeDef
будет сериализован в Json так же, как и вSomeType
случае с ним.Надеюсь это поможет !
источник
Вы можете использовать библиотеку с открытым исходным кодом и пакет NuGet под названием LikeType, который я создал и который даст вам
GenericClass<int>
поведение, которое вы ищете.Код будет выглядеть так:
источник
LikeType
библиотеки.LikeType
Основная цель - помочь с Primitive Obsession , и поэтому он не хочет, чтобы вы могли передавать обернутый тип, как будто это был тип обертки. Например, если я сделаюAge : LikeType<int>
то, если моя функция нуждается вAge
, я хочу убедиться, что мои абоненты передаютAge
, а неint
.Вот код для этого, наслаждайтесь! Я взял это из типа dotNetReference выражение «using» в строке пространства имен 106 http://referencesource.microsoft.com/#mscorlib/microsoft/win32/win32native.cs
источник
Для незапечатанных классов просто наследуйте от них:
Но для закрытых классов можно моделировать поведение typedef с таким базовым классом:
источник
Лучшая альтернатива тому,
typedef
что я нашел в C # - этоusing
. Например, я могу контролировать точность с плавающей точкой с помощью флагов компилятора с помощью этого кода:К сожалению, это требует, чтобы вы поместили это вверху каждого файла, где вы используете
real_t
. В настоящее время нет способа объявить тип глобального пространства имен в C #.источник