Строковое представление Enum

Ваша проблема в том, что «Emp Name» (имя столбца) содержит пробел и должно быть заключено в квадратные скобки в выражении фильтра:

strFilter= strFilter+ " and [Emp Name] = '" + Session["SampleSession"].ToString() + "' ";
880
задан Nisarg 6 February 2018 в 11:20
поделиться

12 ответов

Попробуйте безопасное с точки зрения типов перечисление шаблон.

public sealed class AuthenticationMethod {

    private readonly String name;
    private readonly int value;

    public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");        

    private AuthenticationMethod(int value, String name){
        this.name = name;
        this.value = value;
    }

    public override String ToString(){
        return name;
    }

}
<час>

Обновление Явный (или неявный) преобразование типов может быть сделано [1 111]

  • добавляющее статическое поле с отображением

    private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
    
    • n.b. Чтобы инициализация "перечислимый участник" поля не бросала NullReferenceException при вызове конструктора экземпляра, убедиться поместить поле Dictionary перед "перечислимым участником" поля в классе. Это вызвано тем, что статические полевые инициализаторы называют в порядке объявления, и перед статическим конструктором, создавая странное и необходимое, но путая ситуацию, что конструктор экземпляра можно назвать перед, все статические поля были инициализированы, и прежде чем вызывают статического конструктора.
  • заполнение этого отображения в конструкторе экземпляра

    instance[name] = this;
    
  • и добавление пользовательский оператор

    public static explicit operator AuthenticationMethod(string str)
    {
        AuthenticationMethod result;
        if (instance.TryGetValue(str, out result))
            return result;
        else
            throw new InvalidCastException();
    }
    
преобразования типов
853
ответ дан Jon G 6 February 2018 в 11:20
поделиться
  • 1
    @Faisal Vali, спасибо. я didn' t делают это с только одним op, вызов, потому что существуют типы, которые перегрузка обработала по шаблону op, и которые принимают флаг как второй аргумент (как del << a, b;, который имеет delim operator,(delim,T const&);). Так выполнение (bar(t), flag()) привело бы к неоднозначности. Мы также couldn' t подкачивают порядок, потому что bar(t) мог иметь тип void. При наличии op, флаг принятия, поскольку первый аргумент гораздо менее вероятен, конечно - таким образом что вещь с тремя путями:) – Johannes Schaub - litb 7 September 2009 в 03:51

Опция 1:

public sealed class FormsAuth
{
     public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
     public override string ToString{return "Windows Authtentication";}
}

public sealed class SsoAuth
{
     public override string ToString{return "SSO";}
}

и затем

object auth = new SsoAuth(); //or whatever

//...
//...
// blablabla

DoSomethingWithTheAuth(auth.ToString());

Опция 2:

public enum AuthenticationMethod
{
        FORMS = 1,
        WINDOWSAUTHENTICATION = 2,
        SINGLESIGNON = 3
}

public class MyClass
{
    private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
    public MyClass()
    {
         map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
         map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
         map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
    }
}
4
ответ дан Pablo Retyk 6 February 2018 в 11:20
поделиться
  • 1
    Оборотная сторона этого подхода - то, что я должен изменить свой исходный код для переключения g назад и вперед между g_mock и g_real каждый раз, когда я запускаю свои тесты или свой реальный продукт. – Clint Miller 12 June 2009 в 02:58

Используйте метод

Enum.GetName(Type MyEnumType,  object enumvariable)  

как в (Примите Shipper, определенное Перечисление)

Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);

существует набор других статических методов для Класса Enum, который стоит исследовать также...

224
ответ дан Charles Bretana 6 February 2018 в 11:20
поделиться

Можно сослаться на имя, а не значение при помощи ToString ()

Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());

, документация здесь:

http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx

... и если Вы называете свои перечисления в Pascal-регистре (как я делаю - такие как ThisIsMyEnumValue = 1 и т.д.) тогда Вы могли использовать очень простой regex для печати дружественной формы:

static string ToFriendlyCase(this string EnumString)
{
    return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}

, который можно легко назвать от любой строки:

Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());

Выводы:

Преобразовывают Мое Сумасшедшее Предложение Pascal-регистра В Дружественный Случай

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

мне действительно нравится Ваше исходное решение хотя за более сложные сценарии все же. Вы могли взять свое решение один шаг вперед и сделать Ваш GetStringValue дополнительным методом Вашего перечисления, и затем Вы не должны будете ссылаться на него как StringEnum. GetStringValue...

public static string GetStringValue(this AuthenticationMethod value)
{
  string output = null;
  Type type = value.GetType();
  FieldInfo fi = type.GetField(value.ToString());
  StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
  if (attrs.Length > 0)
    output = attrs[0].Value;
  return output;
}

Вы могли тогда получить доступ к нему легко прямо от Вашего перечислимого экземпляра:

Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
78
ответ дан 7 revs 6 February 2018 в 11:20
поделиться
  • 1
    Существует проблема с этим подходом. Можно отключить наследование объектов в < system.web/> но это ничего не делает к < configSections/> часть. Кто-либо знает, как отключить наследование объектов в < configSections/>? – Ropstah 22 April 2009 в 12:03

я соглашаюсь с Keith, но я (еще) не могу голосовать.

я использую статический метод и swith оператор для возврата точно, что я хочу. В базе данных я храню tinyint, и мой код только использует фактическое перечисление, таким образом, строки для требований UI. После того, как многочисленное тестирование этого привело к лучшей производительности и большей части управления выводом.

public static string ToSimpleString(this enum)
{
     switch (enum)
     {
         case ComplexForms:
             return "ComplexForms";
             break;
     }
}

public static string ToFormattedString(this enum)
{
     switch (enum)
     {
         case ComplexForms:
             return "Complex Forms";
             break;
     }
}

Однако некоторыми учетными записями, это приводит к возможному кошмару обслуживания и некоторому запаху кода. Я пытаюсь бдительно следить для перечислений, которые длинны и много перечислений или тех, которые часто изменяются. Иначе это было отличным решением для меня.

10
ответ дан Tony Basallo 6 February 2018 в 11:20
поделиться

Я использую атрибут Описания от Системы. Пространство имен ComponentModel. Просто украсьте перечисление и затем используйте этот код для получения его:

public static string GetDescription<T>(this object enumerationValue)
            where T : struct
        {
            Type type = enumerationValue.GetType();
            if (!type.IsEnum)
            {
                throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
            }

            //Tries to find a DescriptionAttribute for a potential friendly name
            //for the enum
            MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
            if (memberInfo != null && memberInfo.Length > 0)
            {
                object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

                if (attrs != null && attrs.Length > 0)
                {
                    //Pull out the description value
                    return ((DescriptionAttribute)attrs[0]).Description;
                }
            }
            //If we have no description attribute, just return the ToString of the enum
            return enumerationValue.ToString();

        }

Как пример:

public enum Cycle : int
{        
   [Description("Daily Cycle")]
   Daily = 1,
   Weekly,
   Monthly
}

Этот код приятно обслуживает перечисления, где Вы не нуждаетесь в "Дружественном имени" и возвратите просто.ToString () перечисления.

28
ответ дан Ray Booysen 6 February 2018 в 11:20
поделиться

Когда я сталкиваюсь с этой проблемой, существует несколько вопросов, на которые я пытаюсь найти ответы сначала:

  • названия моих перечислимых значений, достаточно дружественных для цели, или я должен обеспечить более дружественные?
  • мне нужно к распространению в прямом и обратном направлениях? Таким образом, я должен буду принять текстовые значения и проанализировать их в перечислимые значения?
  • это что-то, что я должен сделать для многих перечислений в моем проекте, или всего один?
  • , Какие элементы UI я буду представлять эту информацию в - в частности, я буду связывать с UI или использовать окна свойств?
  • это должно быть локализуемо?

самый простой способ сделать это с Enum.GetValue (и круглое смещение поддержки использование Enum.Parse). Это также часто стоит создать TypeConverter, как Steve Mitcham предполагает, для поддержки привязки UI. (Не необходимо создать TypeConverter при использовании окон свойств который является одной из хороших вещей об окнах свойств. Хотя лорд знает, что у них есть свои собственные проблемы.)

В целом, если ответы на вышеупомянутые вопросы предполагают, что это не собирается работать, мой следующий шаг должен создать и заполнить помехи Dictionary<MyEnum, string>, или возможно Dictionary<Type, Dictionary<int, string>>. Я склонен пропускать промежуточное звено decorate-the-code-with-attributes шаг, потому что, что обычно снижается, пика затем является потребностью изменить дружественные значения после развертывания (часто, но не всегда, из-за локализации).

7
ответ дан Robert Rossney 6 February 2018 в 11:20
поделиться
  • 1
    Isn' t Пассивное Представление, что (почти) вся веб-реализация платформ? Я can' t думают о любых платформах первое, что пришло на ум, которые создали в опросе Ajax для Модели к " notify" Представление. И what' s различие между Пассивным Представлением и 3-уровневый? – Lotus Notes 28 May 2010 в 17:11

К сожалению, отражение для получения атрибутов на перечислениях является довольно медленным:

Посмотрите этот вопрос: Кто-либо знает быстрый способ добраться до пользовательских атрибутов на перечислении значений?

Эти .ToString() является довольно медленным на перечислениях также.

можно записать дополнительные методы для перечислений хотя:

public static string GetName( this MyEnum input ) {
    switch ( input ) {
        case MyEnum.WINDOWSAUTHENTICATION:
            return "Windows";
        //and so on
    }
}

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

<час>

Обновление C#6

, Если можно использовать C#6 тогда новое nameof работы оператора для перечислений, таким образом nameof(MyEnum.WINDOWSAUTHENTICATION) будет преобразован в "WINDOWSAUTHENTICATION" в время компиляции , делая самым быстрым способом получить перечислимые имена.

Примечание, что это преобразует явное перечисление во встроенную константу, таким образом, это не будет работать на перечисления, которые Вы имеете в переменной. Так:

nameof(AuthenticationMethod.FORMS) == "FORMS"

, Но...

var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
68
ответ дан Community 6 February 2018 в 11:20
поделиться
  • 1
    Я не мог использовать " inheritInChildApplications" потому что VS didn' t как он. Что я сделал вместо этого, инвертируют вещи, на которые жаловался IIS при помощи < удалить.../> тег. Это работало на меня. – dyslexicanaboko 9 November 2012 в 23:13

Я использую комбинацию нескольких из предложений выше, объединенный с некоторым кэшированием. Теперь, я получил идею от некоторого кода, что я нашел где-нибудь в сети, но я не могу ни помнить, где я получил его, или найдите его. Таким образом, если кто-либо когда-нибудь находит что-то, что выглядит подобным, прокомментируйте с атрибуцией.

Так или иначе, использование включает конвертеры типов, поэтому если Вы связываете с UI, это 'просто работает'. Вы можете расширенный с помощью шаблона Jakub для быстрого поиска кода путем инициализации из конвертера типов в статические методы.

основное использование было бы похоже на это

[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
    // The custom type converter will use the description attribute
    [Description("A custom description")]
    ValueWithCustomDescription,

   // This will be exposed exactly.
   Exact
}

, код для пользовательского перечислимого конвертера типов следует:

public class CustomEnumTypeConverter<T> : EnumConverter
    where T : struct
{
    private static readonly Dictionary<T,string> s_toString = 
      new Dictionary<T, string>();

    private static readonly Dictionary<string, T> s_toValue = 
      new Dictionary<string, T>();

    private static bool s_isInitialized;

    static CustomEnumTypeConverter()
    {
        System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
          "The custom enum class must be used with an enum type.");
    }

    public CustomEnumTypeConverter() : base(typeof(T))
    {
        if (!s_isInitialized)
        {
            Initialize();
            s_isInitialized = true;
        }
    }

    protected void Initialize()
    {
        foreach (T item in Enum.GetValues(typeof(T)))
        {
            string description = GetDescription(item);
            s_toString[item] = description;
            s_toValue[description] = item;
        }
    }

    private static string GetDescription(T optionValue)
    {
        var optionDescription = optionValue.ToString();
        var optionInfo = typeof(T).GetField(optionDescription);
        if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
        {
            var attribute = 
              (DescriptionAttribute)Attribute.
                 GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
            return attribute.Description;
        }
        return optionDescription;
    }

    public override object ConvertTo(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, 
       object value, Type destinationType)
    {
        var optionValue = (T)value;

        if (destinationType == typeof(string) && 
            s_toString.ContainsKey(optionValue))
        {
            return s_toString[optionValue];
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, object value)
    {
        var stringValue = value as string;

        if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
        {
            return s_toValue[stringValue];
        }

        return base.ConvertFrom(context, culture, value);
    }
}

}

13
ответ дан ErikE 6 February 2018 в 11:20
поделиться
  • 1
    Спасибо. Это похоже на it' s лучше для использования HttpContext. Текущий. Запрос. IsAuthenticated, поскольку это проверяет, что Пользователь и т.д. не является пустым. – Anthony 4 September 2009 в 14:28

Я создал базовый класс для создания перечислений со знаком строки в.NET. Это - всего один файл C#, что можно скопировать & вставьте в свои проекты или установку через пакет NuGet, названный StringEnum. GitHub Repo

  • Intellisense предложит перечислимое имя, если класс будет аннотироваться xml комментарием <completitionlist>. (Работы и в C# и в VB)

Intellisense demo

  • Использование, подобное регулярному перечислению:
///<completionlist cref="HexColor"/> 
class HexColor : StringEnum<HexColor>
{
    public static readonly HexColor Blue = Create("#FF0000");
    public static readonly HexColor Green = Create("#00FF00");
    public static readonly HexColor Red = Create("#000FF");
}
    // Static Parse Method
    HexColor.Parse("#FF0000") // => HexColor.Red
    HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
    HexColor.Parse("invalid") // => throws InvalidOperationException

    // Static TryParse method.
    HexColor.TryParse("#FF0000") // => HexColor.Red
    HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
    HexColor.TryParse("invalid") // => null

    // Parse and TryParse returns the preexistent instances
    object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true

    // Conversion from your `StringEnum` to `string`
    string myString1 = HexColor.Red.ToString(); // => "#FF0000"
    string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)

Instalation:

  • Вставка следующий базовый класс StringEnum к Вашему проекту. ( последняя версия )
  • Или установка пакет StringEnum NuGet, который основан .Net Standard 1.0, таким образом, это работает .Net Core> = 1.0, .Net Framework> = 4.5, Mono> = 4.6, и т.д.
    /// <summary>
    /// Base class for creating string-valued enums in .NET.<br/>
    /// Provides static Parse() and TryParse() methods and implicit cast to string.
    /// </summary>
    /// <example> 
    /// <code>
    /// class Color : StringEnum &lt;Color&gt;
    /// {
    ///     public static readonly Color Blue = Create("Blue");
    ///     public static readonly Color Red = Create("Red");
    ///     public static readonly Color Green = Create("Green");
    /// }
    /// </code>
    /// </example>
    /// <typeparam name="T">The string-valued enum type. (i.e. class Color : StringEnum&lt;Color&gt;)</typeparam>
    public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
    {
        protected string Value;
        private static Dictionary<string, T> valueDict = new Dictionary<string, T>();
        protected static T Create(string value)
        {
            if (value == null)
                return null; // the null-valued instance is null.

            var result = new T() { Value = value };
            valueDict.Add(value, result);
            return result;
        }

        public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
        public override string ToString() => Value;

        public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
        public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;

        public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
        bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
        public override int GetHashCode() => Value.GetHashCode();

        /// <summary>
        /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
        /// </summary>
        /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
        /// <param name="caseSensitive">If true, the strings must match case and takes O(log n). False allows different case but is little bit slower (O(n))</param>
        public static T Parse(string value, bool caseSensitive = true)
        {
            var result = TryParse(value, caseSensitive);
            if (result == null)
                throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");

            return result;
        }

        /// <summary>
        /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
        /// </summary>
        /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
        /// <param name="caseSensitive">If true, the strings must match case. False allows different case but is slower: O(n)</param>
        public static T TryParse(string value, bool caseSensitive = true)
        {
            if (value == null) return null;
            if (valueDict.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
            if (caseSensitive)
            {
                if (valueDict.TryGetValue(value, out T item))
                    return item;
                else
                    return null;
            }
            else
            {
                // slower O(n) case insensitive search
                return valueDict.FirstOrDefault(f => f.Key.Equals(value, StringComparison.OrdinalIgnoreCase)).Value;
                // Why Ordinal? => https://esmithy.net/2007/10/15/why-stringcomparisonordinal-is-usually-the-right-choice/
            }
        }
    }
4
ответ дан 22 November 2019 в 21:03
поделиться

Если вы думаете о проблеме, которую мы пытаемся решить, это совсем не перечисление, которое нам нужно. Нам нужен объект, который позволяет связать определенное количество значений друг с другом; другими словами, чтобы определить класс.

Типобезопасный шаблон перечисления Якуба Штурца - лучший вариант, который я вижу здесь.

Посмотрите на него:

  • Он имеет частный конструктор, поэтому только сам класс может определять допустимые значения.
  • Это запечатанный класс, поэтому значения не могут быть изменены посредством наследования.
  • Он безопасен по типу, позволяя вашим методам требовать только этот тип.
  • Нет никакого снижения производительности отражения, вызванного доступ к значениям.
  • И, наконец, его можно изменить, чтобы связать вместе более двух полей, например Имя, Описание и числовое значение.
4
ответ дан 22 November 2019 в 21:03
поделиться

на основе MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx

foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
    Debug.WriteLine(str);
}

str будут именами полей

2
ответ дан 22 November 2019 в 21:03
поделиться
Другие вопросы по тегам:

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