2014-09-04 3 views
1

C에서는 입력을 문자열로 입력을 대체하는 매크로 함수를 작성할 수 있습니다.C에서 하나의 표현식을 두 번 사용할 수있는 C 스타일의 지시문 #define x (k) {#k, k}

#define x(k) {#k, k} 

'(4)'를 생성 할 "{"4 ", 4}

내가 단위 테스트 이런 입력을 전달할 여기서 I는 C#에서 쓰임새가있다.

private void AssertInt64Expression(Int64 i, string str) 
{ 
    Assert.AreEqual(i, MathFactory.make(str)); 
} 

[Test] 
public void ParseBasic() 
{ 
    AssertInt64Expression(4, "4"); 
    AssertInt64Expression(2+3, "2+3"); 
    AssertInt64Expression(7-11, "7-11"); 
    AssertInt64Expression(7-11 *2, "7-11 *2"); 
    AssertInt64Expression(7 - 11 * 2, "7 - 11 * 2"); 
} 

본질적으로 정보 (공백 포함)를 반복합니다. 어떻게 C 스타일 매크로와 같은 것을 사용하여 C에서 해결할 수 있습니까?


편집 :

은 본질적으로 내가 쓰고 싶어요 :

private void AssertInt64Expression(GeneratorMagic magic) 
{ 
    Assert.AreEqual(magic.ToCode(), MathFactory.make(magic.ToString())); 
} 

[Test] 
public void ParseBasic() 
{ 
    AssertInt64Expression(<#7 - 11 * 2#>); 
} 

나는이 컴파일하지 않을 것이라고 알고 있습니다.


편집 :

나는 내가 무엇을 찾고 설명하기 위해 답변으로 코드를 추가했습니다. 그러나이 스 니펫은 매우 느리게 실행됩니다. 적은 단위로 더 깨끗한 코드로 리팩터링하는 것이 필요하기 때문에 스 니펫이 더 빨리 실행되어야합니다. 스 니펫은 원래 편집본의 magicKeyValuePair으로 제공합니다.

+1

[코드 생성 및 T4 텍스트 템플릿] (http://msdn.microsoft.com/en-us/library/bb126445.aspx)이 실제로 도움이 될지 모르겠다. –

+1

귀하의 [코멘트가] (http://stackoverflow.com/questions/709463/c-sharp-macro-definitions-in-preprocessor#comment40110288_709475)에 따르면 [C# 매크로 정의가 전처리 기]라는 질문을 발견했습니다 (http : //stackoverflow.com/questions/709463/c-sharp-macro-definitions-in-preprocessor). 귀하의 질문에 대답이 없습니까 (대답은 "아니오"입니까)? – CodeCaster

+0

@ CodeCaster 답변을 찾았는데 전처리기를 찾지 못했습니다. 나는 두 번보다는 somethign 한 번 쓰고 싶은 usecase 있고 어떻게 C#에서 이루어집니다 찾고 있어요. 이것이 불가능할 것 같지 않습니다. – Johannes

답변

0

다음 스 니펫은 내가 필요로하는 것이지만 끔찍하게 느리게 실행되는 것 같습니다.

private KeyValuePair<String, Int64> GenerateCodeInt64(String mathKey) 
    { 
     string codeNamespace = "MathTestCalculator"; 
     string codeClassName = "MathTestCalculator"; 
     string codeMethodName = "Value"; 

     Int64 I64Value = 0; 
     StringBuilder codeBuilder = new StringBuilder(); 

     codeBuilder 
      .Append("using System;\n") 
      .Append("namespace ").Append(codeNamespace).Append(" {\n") 
      .Append("class ").Append(codeClassName).Append("{\n") 
      .Append("public Int64 ").Append(codeMethodName).Append("(){\n") 
      .Append("return (Int64)(").Append(mathKey).Append(");}}}\n"); 

     CompilerParameters cp = new CompilerParameters(); 
     cp.GenerateExecutable = false; 
     cp.GenerateInMemory = true; 

     CompilerResults results = CodeDomProvider 
      .CreateProvider("CSharp") 
      .CompileAssemblyFromSource(cp, codeBuilder.ToString()); 

     if (results.Errors.Count > 0) 
     { 
      StringBuilder error = new StringBuilder(); 
      error.Append("Unable to evaluate: '").Append(mathKey).Append("'\n"); 
      foreach (CompilerError CompErr in results.Errors) 
      { 
       error 
        .Append("Line number ").Append(CompErr.Line) 
        .Append(", Error Number: ").Append(CompErr.ErrorNumber) 
        .Append(", '").Append(CompErr.ErrorText).Append(";\n"); 
      } 
      throw new Exception(error.ToString()); 
     } 
     else 
     { 
      Type calcType = results.CompiledAssembly.GetType(codeNamespace + "." + codeClassName); 
      object o = Activator.CreateInstance(calcType); 
      I64Value = (Int64)calcType.GetMethod(codeMethodName).Invoke(o, null); 
     } 
     return new KeyValuePair<string, long>(mathKey, I64Value); 
    } 
0

오버로드 된 연산자가있는 사용자 정의 숫자 클래스를 사용할 수 있습니다.

static void Main(string[] args) 
{ 
    Console.WriteLine((Number)1 + 5); 
    Console.WriteLine((int)((Number)1 + 5 + 6)); 

} 

public class Number 
{ 
    private string _representation = ""; 
    private int _number = 0; 

    private Number(int n) 
    { 
     _number = n; 
     _representation = n.ToString(); 
    } 

    public Number Plus(int n) 
    { 
     _representation += " + " + n; 
     _number += n; 
     return this; 
    } 

    public static Number operator +(Number value1, int value2) 
    { 
     return value1.Plus(value2); 
    } 

    public static explicit operator Number(int val) 
    { 
     return new Number(val); 
    } 

    public static explicit operator int(Number num) 
    { 
     return num._number; 
    } 

    public override string ToString() 
    { 
     return _representation; 
    } 
} 
+0

포인트는 문자열 생성기를 내 수학 생성기에 공급하고 그 결과를 본질적으로 C#이 생성기없이 계산할 것으로 예상되는 결과와 비교하는 것입니다. 귀하의 예제는 제한된 세트에서 작동하고 공백의 영향에 대해 테스트하고 싶다면 실패합니다. "1 + 1"은 "1 + 1"과 다릅니다. – Johannes

+0

Number 클래스에 메소드를 추가하여 주어진 입력에 대해 가능한 모든 공백 구성을 생성 할 수 있습니다. – brz

관련 문제