Дженерики и nullable тип

Существуют углы emacs, который когда-то обнаружил, делают Вас более продуктивными способами, которыми Вы никогда не думали. Как другие упомянули, использование отмечает, фантастический и быстрый способ масштабировать вокруг Вашего исходного кода, и использующий M-/(dabbrev-расширяются), часто делает точно, что Вы ожидаете при завершении имени переменной.

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

строки сброса, числовые поля вида, замена-regexp и прямоугольные функции могут быть действительно полезны для взятия дампа от некоторого инструмента и преобразования его к полезным данным, таким как elisp программа, или запятая разграничила электронную таблицу.

я записал страницу о IDE как вещи, которые можно сделать с emacs

http://justinsboringpage.blogspot.com/2007/09/11-visual-studio-tricks-in-emacs.html

, Учась elisp, другой отличный способ ответить для себя, что еще emacs может сделать вне того, что может сделать типичный IDE.

, Например, я вел блог о записи По необходимости функций помощника как вина (пишущий, что Ваше собственное означает, что можно заставить ее вести себя точно, как Вы хотите)...

http://justinsboringpage.blogspot.com/2009/01/who-changed-line-your-working-on-last.html

я также написал код, который динамично создает комментарии для функции в точке, которая соответствует стандартам кодирования, с которыми я работаю.

Ни один из моего кода elisp не является особенно большим, и большая часть из него уже существует в библиотеках, но действительно полезно смочь заставить emacs сделать пользовательский материал, который просто подходит в течение рабочего дня.

8
задан Phillip Ngan 10 December 2009 в 06:29
поделиться

5 ответов

Забавно, что вы упомянули об этом, потому что на днях я возился с чем-то вроде этого:

using System;
using System.Reflection;

static class Example
{
    public static Tuple<Boolean, T?> TryParse<T>(this String candidate)
        where T : struct
    {
        T? value = null;
        Boolean success = false;

        var parser = ParsingBinder<T>.GetParser();

        try 
        { 
                value = parser(candidate);
                success = true;
        } 
        catch (FormatException) { }

        return new Tuple<Boolean,T?>(success, value);
    }
}

static class ParsingBinder<T>
{
    static Func<String, T> parser;

    public static Func<String, T> GetParser()
    {
        if (parser == null)
                parser = getParser();

        return parser;
    }

    static Func<String, T> getParser()
    {
        MethodInfo methodInfo 
            = typeof(T).GetMethod(
                    "Parse", new [] { typeof(String) });

        if (methodInfo == null)
                throw new Exception(
                        "Unable to retrieve a \"Parse\" method for type.");

        return (Func<String, T>)Delegate
        .CreateDelegate(typeof(Func<String, T>), methodInfo);
    }
}

Это похожий подход, но подумайте о нем как о лучшем TryParse , который возвращает Tuple (для этого требуется .NET 4). Первое свойство кортежа - это логическое значение, указывающее успех или неудачу попытки синтаксического анализа, а второе свойство - значение, допускающее значение NULL, введенное в аргумент универсального типа, которое будет null , если синтаксический анализ завершится неудачно, и значение, если разбор завершается успешно.

Он работает, используя отражение для получения статического метода Parse (String) из аргумента универсального типа и вызывает этот метод для строки, которая передается. Я создал его как метод расширения чтобы вы могли делать такие вещи:

var intValue = "1234".TryParse<Int32>();
var doubleValue = "1234".TryParse<Double>();

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

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


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

Я лично считаю этот шаблон довольно уродливым:

Int32 value;
if (Int32.TryParse(someString, out value))
    // do something with value

главным образом потому, что он требует предварительного объявления переменной и использования параметра out . Мой подход, описанный выше, на самом деле не намного лучше:

var result = someString.TryParse<Int32>();
if (result.Item1)
    // do something with result.Item2

Было бы здорово увидеть расширение языка C #, которое было создано для работы с Tuple , что позволило бы нам, чтобы работать с этим типом гладко, но, чем больше я пишу об этом, у меня возникает ощущение, что это на самом деле не представляется возможным.

14
ответ дан 5 December 2019 в 07:11
поделиться

Вместо вопросительного знака вы можете явно использовать ключевое слово Nullable: например,

int? равно Nullable

Поэтому переключение исходного дизайна на Nullable ParseValue (string valueAsString ) должно помочь: просто сделайте общая реализация после этого.

3
ответ дан 5 December 2019 в 07:11
поделиться

Если вы можете подождать для C # 4.0 вы можете использовать ключевое слово dynamic , которое решает такой сценарий.

2
ответ дан 5 December 2019 в 07:11
поделиться

Все перечисленные вами типы имеют статический метод под названием TryParse. На вид они похожи, но на самом деле подписи совершенно разные. Они следуют аналогичному «шаблону», но компилятор не обнаруживает его.

Вы можете попробовать сделать что-то вроде этого:

    public T? ParseValue<T>(string value) where T : struct
    {
        if (typeof(T) == typeof(int))
        {
            int i;
            if (int.TryParse(value, out i))
                return (T)(object)i;
            return null;
        }
        if (typeof(T) == typeof(decimal)) 
        {
            decimal d;
            if (decimal.TryParse(value, out d))
                return (T)(object)d;
            return null;
        }
        // other supported types...
        throw new ArgumentException("Type not supported");
    }

Однако вы не можете. У компилятора нет способа узнать (во время компиляции), как преобразовать тип 'T' в int (или любой другой тип).

Вы можете выполнить двойное приведение, чтобы это сработало. (Спасибо, Дотсон)

Использование:

        var mydecimal = ParseValue<decimal>("12.1");
        var myint = ParseValue<int>("-22");
        var badint = ParseValue<int>("Bad");
        // badint.HasValue == false
0
ответ дан 5 December 2019 в 07:11
поделиться

На самом деле, вы можете обновить то, что сделал код Мэтта, и сделать это, и вот код:

enter code here:static T? TryParse<T>(string parse)
        where T : struct
    {
        Type t=typeof(T);
        if (t==typeof(int))
        {
            int i;
            if (int.TryParse(parse, out i))
                return (T)(object)i;
            return null;
            //Console.WriteLine(t.Name);
        }
        if (t == typeof(double))
        {
            double i;
            if (double.TryParse(parse, out i))
                return (T)(object)i;
            return null;
        }
        //blabla, more logic like datetime and other data types
        return null;
    }

А также вы можете использовать его так: двойной? я = TryParse ("111,111"); int? a = TryParse ("111");

0
ответ дан 5 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

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