Логгинг с именами функций и номерами строк
От: BigBoss  
Дата: 10.08.17 20:07
Оценка:
Как известно, __LINE__, __FILE__ вместе с макро в C# не попали.
StackFrame медленный и вообще не должен компилироваться в native (не пробовал, но рефлексии там вроде нет).
К версии 4.5 появились System.Runtime.CompilerServices, но "в лоб" это тоже не работает. Вариации на тему

    void LogMessage(string format, object[] args,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
    {
        string msg = string.Format(format, args);
        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, msg);
    }

компилируется, но естественно не так, как хотелось бы, аттрибуты на сопоставление параметров не влияют. Попробуйте сами

    LogMessage("Hello, world");
    LogMessage("Hello, {0}", "world");
    LogMessage("{0}, {1}", "Hello", "world");

А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?
Re: Логгинг с именами функций и номерами строк
От: rameel https://github.com/rsdn/CodeJam
Дата: 10.08.17 22:49
Оценка:
Здравствуйте, BigBoss, Вы писали:

BB>К версии 4.5 появились System.Runtime.CompilerServices, но "в лоб" это тоже не работает.


Почему не работают и что значит в лоб?

  Скрытый текст
BB>
BB>    void LogMessage(string format, object[] args,
BB>        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
BB>        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
BB>        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
BB>    {
BB>        string msg = string.Format(format, args);
BB>        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, msg);
BB>    }
BB>

BB>компилируется, но естественно не так, как хотелось бы, аттрибуты на сопоставление параметров не влияют.

Вот здесь не понял

BB>
BB>    LogMessage("Hello, world");
BB>    LogMessage("Hello, {0}", "world");
BB>    LogMessage("{0}, {1}", "Hello", "world");
BB>


Вот это у тебя вообще не скомпилируется

BB>А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?


Воспользоваться например T4 и сгенерировать методы с нужным набором параметров, чтобы не создавать массив для args
void LogMessage(string format, object arg
void LogMessage(string format, object arg0, object arg1
void LogMessage(string format, object arg0, object arg1, object arg2
void LogMessage(string format, object arg0, object arg1, object arg2, object arg3
...
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: Логгинг с именами функций и номерами строк
От: BigBoss  
Дата: 11.08.17 08:37
Оценка: 10 (1)
Здравствуйте, rameel, Вы писали:

BB>>К версии 4.5 появились System.Runtime.CompilerServices, но "в лоб" это тоже не работает.

R>Почему не работают и что значит в лоб?

BB>>
BB>>    void LogMessage(string format, object[] args,
BB>>        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
BB>>        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
BB>>        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
BB>>    {
BB>>        string msg = string.Format(format, args);
BB>>        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, msg);
BB>>    }
BB>>


В лоб -- это буквально как написано. А не работает потому, что если список параметров концается на строку/две строки/две строки+целое, то эти параметры естественным образом попадают не в args, а в memberName/sourceFilePath/sourceLineNumber.

BB>>компилируется, но естественно не так, как хотелось бы, аттрибуты на сопоставление параметров не влияют.


R>Вот здесь не понял


Запускаем, получаем

T:\varargs\Program.cs Main:48 'Hello, world'
T:\varargs\Program.cs world:49 'Hello, {0}'
world Hello:50 '{0}, {1}'



BB>>
BB>>    LogMessage("Hello, world");
BB>>    LogMessage("Hello, {0}", "world");
BB>>    LogMessage("{0}, {1}", "Hello", "world");
BB>>


R>Вот это у тебя вообще не скомпилируется


Да, я опустил прототип LogMessage без args[] и Format().

BB>>А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?


R>Воспользоваться например T4 и сгенерировать методы с нужным набором параметров, чтобы не создавать массив для args


оно так и было изначально написано, это ничего не меняет в связывании формальных и фактических параметров. Пример с массивом я для краткости привел
Отредактировано 13.08.2017 12:15 VladD2 . Предыдущая версия .
Re[3]: Логгинг с именами функций и номерами строк
От: rameel https://github.com/rsdn/CodeJam
Дата: 11.08.17 08:53
Оценка:
Здравствуйте, BigBoss, Вы писали:

Да, полную фигню сморозил. Спать надо ночью! Это я про себя
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: Логгинг с именами функций и номерами строк
От: hardcase Пират http://nemerle.org
Дата: 16.08.17 11:24
Оценка: 10 (1)
Здравствуйте, BigBoss, Вы писали:

BB>А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?


Остается вариант с интерполяцией строк.

using System;

public class Test
{
    public static void Log(FormattableString message,
    [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
    {
        Console.WriteLine(message.ToString());
        Console.WriteLine(sourceFilePath + ":" + sourceLineNumber);
    }
    
    public static void Main()
    {
        Log($"Foo: {1}");
    }
}
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Логгинг с именами функций и номерами строк
От: kov_serg Россия  
Дата: 16.08.17 13:58
Оценка: 2 (1)
Здравствуйте, BigBoss, Вы писали:

BB>Как известно, __LINE__, __FILE__ вместе с макро в C# не попали.

BB>StackFrame медленный и вообще не должен компилироваться в native (не пробовал, но рефлексии там вроде нет).
BB>К версии 4.5 появились System.Runtime.CompilerServices, но "в лоб" это тоже не работает. Вариации на тему

BB>
BB>    void LogMessage(string format, object[] args,
BB>        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
BB>        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
BB>        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
BB>    {
BB>        string msg = string.Format(format, args);
BB>        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, msg);
BB>    }
BB>

BB>компилируется, но естественно не так, как хотелось бы, аттрибуты на сопоставление параметров не влияют. Попробуйте сами

BB>
BB>    LogMessage("Hello, world");
BB>    LogMessage("Hello, {0}", "world");
BB>    LogMessage("{0}, {1}", "Hello", "world");
BB>

BB>А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?
using System;
using System.Runtime.CompilerServices;
using System.Globalization;

public static class StringFmtExt {
    public static string fmt(this string fmt,params object[] args)
    {
        return string.Format(CultureInfo.InvariantCulture,fmt,args);
    }
}

public class Test {

    static void Log(string msg,
            [CallerMemberName] string memberName="",
            [CallerFilePath] string sourceFilePath="",
            [CallerLineNumber] int sourceLineNumber=0
    )
    {
        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, msg);
    }
    
    public delegate void LogDelegate(string fmt,params object[] args);
    static LogDelegate LogPoint(
        [CallerMemberName] string memberName="",
        [CallerFilePath] string sourceFilePath="",
        [CallerLineNumber] int sourceLineNumber=0) 
    {
        return (fmt,args)=>{
            var text=string.Format(CultureInfo.InvariantCulture,fmt,args);
            Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, text);
        };
    }
    static void Debug(Action<LogDelegate> op,
        [CallerMemberName] string memberName="",
        [CallerFilePath] string sourceFilePath="",
        [CallerLineNumber] int sourceLineNumber=0) 
    {
        op( (fmt,args)=>{
            var text=string.Format(CultureInfo.InvariantCulture,fmt,args);
            Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, text);
        });
    }

    static void Log0(string fmt, object[] args,
            [CallerMemberName] string memberName="",
            [CallerFilePath] string sourceFilePath="",
            [CallerLineNumber] int sourceLineNumber=0
    )
    {
        var text=string.Format(CultureInfo.InvariantCulture,fmt,args);
        Console.WriteLine("{0} {1}:{2} '{3}'", sourceFilePath, memberName, sourceLineNumber, text);
    }
    
    public static void Main()
    {
        Log("test {0} {1}".fmt(1,2));
        LogPoint()("test {0} {1}",1,2);
        Log0("test {0} {1}",new object[] { 1,2 });
        Debug(log=>log("test {0} {1}",1,2));
    }
}

prog.cs Main:57 'test 1 2'
prog.cs Main:58 'test 1 2'
prog.cs Main:59 'test 1 2'
prog.cs Main:60 'test 1 2'
Отредактировано 16.08.2017 14:03 kov_serg . Предыдущая версия .
Re[2]: Логгинг с именами функций и номерами строк
От: BigBoss  
Дата: 16.08.17 22:45
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, BigBoss, Вы писали:


BB>>А как (можно ли вообще) на C# написать функцию вроде LogMessage, но работающую и без черезмерного синтаксического оверхеда?


H>Остается вариант с интерполяцией строк.


Спасибо, то что нужно!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.