Существует ли способ определить псевдонимы со строгим контролем типов C# существующих типов примитивов как 'строка' или 'интервал'?

Возможно, я демонстрирую свое незнание некоторых часто используемый feautre C# или платформы.NET, но я хотел бы знать, существует ли исходно поддерживаемый способ создать псевдоним типа как EmailAddress который искажает string но таким образом, что я могу расширить его с помощью своих собственных методов как bool Validate()?

Я знаю о using x = Some.Type; псевдонимы, но они не глобальны, и при этом они не обеспечивают безопасность типов, т.е. можно было выгрузить дежурное блюдо string поскольку использование искажает в текущем файле. Я хотел бы мой EmailAddress быть его собственным типом, независимым и не взаимозаменяемый string введите это это тени.

Мое текущее решение состоит в том, чтобы генерировать public sealed partial EmailAddress : IEquatable<EmailAddress>, IXmlSerializable классы с шаблоном T4, генерирующим шаблон неявные операторы преобразования строк и другие такие вещи. Это меня устраивает на данный момент и дает мне большую гибкость, но подсознательно кажется глупым, что я должен генерировать такие обильные объемы шаблонного кода, чтобы сделать что-то столь же простое как создание сильного псевдонима типа.

Возможно, это не возможно кроме с генерацией кода, но мне любопытно, если другие делали попытку чего-то похожего со своими проектами и каковы Ваши события были. Если ничто иное, возможно, это могло бы служить хорошим примером использования для такой функции псевдонима в гипотетической будущей версии C#. Спасибо!

Править: Действительное значение, которое я хочу из этого, состоит в том, чтобы быть в состоянии получить безопасность типов с типами примитивов, которые представляют различные типы/форматы для данных. Например, EmailAddress и a SocialSecurityNumber и a PhoneNumber, все из которых используют string как их базовый тип, но которые не являются взаимозаменяемыми типами в и себя. Я думаю, что это получает Вас намного больше читаемого и самодокументирующего кода, не говоря уже о дополнительных преимуществах большего количества возможностей перегрузки метода, которые менее неоднозначны.

18
задан James Dunne 18 December 2009 в 01:43
поделиться

6 ответов

If you look at the .NET Framework System.Uri is the closest example that is similar to an email address. In .NET the pattern is to wrap something in a class and add constraints that way.

Adding strong typing that adds additional constraints to simple types is an interesting language feature that I believe some functional language has. I can't recall the name of the language which would let you add dimensional units such as feet to your values and do a dimensional analysis on your equations to ensure that the units matched.

5
ответ дан 30 November 2019 в 09:18
поделиться

I think you want to use extension methods. They allow you to extend a classes functionality without creating a new derived type.

1
ответ дан 30 November 2019 в 09:18
поделиться

Некоторые сведения о том, почему строка запечатана:

От http://www.code-magazine.com/Article.aspx?quickid=0501091 :

Рори: Эй, Джей, ты не возражаешь, если я спрошу тебя пара вопросов? Мне уже любопытно о некоторых вещах. Прежде всего, и это было поднято на одном из MSDN события, которые я провел на этой неделе, почему String запечатанный? Примечание: для программистов VB.NET, Sealed = NotInheritable.

Джей: Потому что мы творит много магии. трюки в String, чтобы попробовать и убедиться мы можем оптимизировать такие вещи, как сравнения, чтобы сделать их так быстро, как мы, возможно, сможем. Итак, мы воруем кусочки указателей и прочего там, чтобы пометить вещи. Просто приведу вам пример, а я не знал это когда я начал, но если строка в нем есть дефис или апостроф [затем] он сортируется иначе, чем если бы просто содержит текст, а алгоритм для сортировки, если у вас есть дефис или апостроф, если вы делаете глобальная сортировка довольно хороша сложно, поэтому мы фактически отмечаем есть ли у строки это тип поведения в нем.

Рори: Итак, вы говорите, что в мире струн, если ты не печать String там было бы много места для того, чтобы нанести большой ущерб, если люди пытались создать подклассы.

Джей: Совершенно верно. Это изменило бы весь макет объекта, поэтому мы не смог бы разыграть трюки что мы играем с такой скоростью.

Вот статья CodeProject, которую вы, вероятно, видели раньше:

http://www.codeproject.com/KB/cs/expandSealed.aspx

Так что да, неявный Оператор - ваше единственное решение.

4
ответ дан 30 November 2019 в 09:18
поделиться

It seems you have at least a reasonable C# knoledgde so my answer may seem stupid, but what you want is called "type hierarchy" and the guys who coded the String class wanted to prevent you from using this "OO feature" so they made String class sealed, that's why you won't be able to do what you want. The best approach is this you are on now: Make your own type and an implicit convertion to String.

2
ответ дан 30 November 2019 в 09:18
поделиться

Подходит ли класс System.Net.Mail.MailAddress вашим потребностям или, по крайней мере, «помогает»?

РЕДАКТИРОВАТЬ: Это явно не IEquatable или ISerializable, но вы можете легко добавить их в свою собственную оболочку.

2
ответ дан 30 November 2019 в 09:18
поделиться

I guess I do not get why you want to have both strong types AND implicit string conversion at the same time. For me, one rules out the other.

I tried to solve the same problem for ints (you mention int in the title, but not in the question). I found that declaring an enum gives you a type-safe integer which needs to be explicitly cast from/to int.

Update

Enums may not be intended for open sets, but can still be used in such a way. This sample is from a compilation experiment to distinguish between the ID columns of several tables in a database:

    enum ProcID { Unassigned = 0 }
    enum TenderID { Unassigned = 0 }

    void Test()
    {
        ProcID p = 0;
        TenderID t = 0; <-- 0 is assignable to every enum
        p = (ProcID)3;  <-- need to explicitly convert

        if (p == t)  <-- operator == cannot be applied
            t = -1;  <-- cannot implicitly convert

        DoProc(p);
        DoProc(t);   <-- no overloaded method found
        DoTender(t);
    }

    void DoProc(ProcID p)
    {
    }

    void DoTender(TenderID t)
    {
    }
1
ответ дан 30 November 2019 в 09:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: