Подтвердить что ты не робот

Определения макросов С# в препроцессоре

Может ли С# определять макросы, как это делается на языке программирования C, с инструкциями перед процессором? Я хотел бы упростить регулярное типирование некоторых повторяющихся утверждений, таких как:

Console.WriteLine("foo");
4b9b3361

Ответ 1

Нет, С# не поддерживает макросы препроцессора, такие как C. Visual Studio, с другой стороны, имеет фрагменты. Фрагменты Visual Studio - это функция IDE и расширены в редакторе, а не заменены в коде при компиляции препроцессором.

Ответ 2

Вы можете использовать препроцессор C (например, mcpp) и установить его в файл .csproj. Затем вы выполняете "build action" в исходном файле из "Скомпилировать в Preprocess" или как вы его называете. Просто добавьте BeforBuild в свой .csproj следующим образом:

  <Target Name="BeforeBuild" Inputs="@(Preprocess)" Outputs="@(Preprocess->'%(Filename)_P.cs')">
<Exec Command="..\Bin\cpp.exe @(Preprocess) -P -o %(RelativeDir)%(Filename)_P.cs" />
<CreateItem Include="@(Preprocess->'%(RelativeDir)%(Filename)_P.cs')">
  <Output TaskParameter="Include" ItemName="Compile" />
</CreateItem>

Возможно, вам придется вручную скомпилировать Compile to Preprocess по крайней мере в одном файле (в текстовом редакторе) - тогда опция "Preprocess" должна быть доступна для выбора в Visual Studio.

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

Ответ 3

Я использую это, чтобы избежать Console.WriteLine(...):

public static void Cout(this string str, params object[] args) { 
    Console.WriteLine(str, args);
}

а затем вы можете использовать следующее:

"line 1".Cout();
"This {0} is an {1}".Cout("sentence", "example");

это кратким и любезным напуганным.

Ответ 4

Пока вы не можете писать макросы, когда дело доходит до упрощения таких вещей, как ваш пример, С# 6.0 теперь предлагает статические приложения. Здесь пример Мартина Перника дал его среднюю статью:

using static System.Console; // Note the static keyword

namespace CoolCSharp6Features
{
  public class Program
  {
    public static int Main(string[] args)
    {
      WriteLine("Hellow World without Console class name prefix!");

      return 0;
    }
  }
}

Ответ 5

Прямой эквивалент макросов C-стиля в С#, но inline d статические методы - с или без #if/#elseif/#else прагмы - это самое близкое, которое вы можете получить:

        /// <summary>
        /// Prints a message when in debug mode
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void Log(object message) {
#if DEBUG
            Console.WriteLine(message);
#endif
        }

        /// <summary>
        /// Prints a formatted message when in debug mode
        /// </summary>
        /// <param name="format">A composite format string</param>
        /// <param name="args">An array of objects to write using format</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void Log(string format, params object[] args) {
#if DEBUG
            Console.WriteLine(format, args);
#endif
        }

        /// <summary>
        /// Computes the square of a number
        /// </summary>
        /// <param name="x">The value</param>
        /// <returns>x * x</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double Square(double x) {
            return x * x;
        }

        /// <summary>
        /// Wipes a region of memory
        /// </summary>
        /// <param name="buffer">The buffer</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void ClearBuffer(ref byte[] buffer) {
            ClearBuffer(ref buffer, 0, buffer.Length);
        }

        /// <summary>
        /// Wipes a region of memory
        /// </summary>
        /// <param name="buffer">The buffer</param>
        /// <param name="offset">Start index</param>
        /// <param name="length">Number of bytes to clear</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void ClearBuffer(ref byte[] buffer, int offset, int length) {
            fixed(byte* ptrBuffer = &buffer[offset]) {
                for(int i = 0; i < length; ++i) {
                    *(ptrBuffer + i) = 0;
                }
            }
        }

Это отлично работает как макрос, но имеет небольшой недостаток: методы, помеченные как inline d, будут скопированы в часть отражения вашей сборки, как и любой другой "нормальный" метод.

Ответ 6

К счастью, у С# нет препроцессора в стиле C/С++ - поддерживаются только условная компиляция и прагмы (и, возможно, что-то еще, что я не могу вспомнить). К сожалению, у С# нет возможностей метапрограммирования (это может в какой-то мере иметь отношение к вашему вопросу).

Ответ 7

Поверните макрос C в статический метод С# в классе.

Ответ 8

Я бы предложил вам написать расширение, что-то вроде ниже.

public static class WriteToConsoleExtension
{
   // Extension to all types
   public static void WriteToConsole(this object instance, 
                                     string format, 
                                     params object[] data)
   {
       Console.WriteLine(format, data);
   }
}

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        // Usage of extension
        p.WriteToConsole("Test {0}, {1}", DateTime.Now, 1);
    }
}

Надеюсь, что это поможет (и не слишком поздно:))

Ответ 9

Поскольку С# 7.0 поддерживает using static директив и локальных функций, для большинства случаев вам не нужны макросы препроцессора.