program story

메서드에서 익명 유형을 반환하는 방법이 있습니까?

inputbox 2020. 11. 23. 08:06
반응형

메서드에서 익명 유형을 반환하는 방법이 있습니까?


다음과 같은 메서드를 작성할 수 없다는 것을 알고 있습니다.

public var MyMethod()
{
   return new{ Property1 = "test", Property2="test"};
}

그렇지 않으면 할 수 있습니다.

public object MyMethod()
{
   return new{ Property1 = "test", Property2="test"}
}

하지만 두 번째 옵션은하고 싶지 않습니다. 그렇게하면 리플렉션을 사용해야하기 때문입니다.


내가 원하는 이유 :

오늘 나는 결과로 데이터 테이블을 반환하는 내 aspx 페이지 내부에 메서드가 있으며 변경할 수 없습니다. 이 DataTable을 작업하려는 속성이있는 익명 메서드로 변환하려고했습니다. 그렇게하기 위해서만 클래스를 만들고 싶지 않았고 동일한 쿼리를 두 번 이상 수행해야하므로 익명 유형을 반환하는 메서드를 만드는 것이 좋은 아이디어가 될 것이라고 생각했습니다.


A와 그것을 반환하기 System.Object는 IS 유일한 방법에서 익명 형식을 반환하는 방법. 안타깝게도 익명 유형이 이러한 방식으로 사용되는 것을 방지하도록 특별히 설계 되었기 때문에이를 수행하는 다른 방법은 없습니다.

Object가까워 질 수 있도록를 반환하는 것과 함께 수행 할 수있는 몇 가지 트릭이 있습니다 . 이 해결 방법에 관심이있는 경우 메서드에서 익명 형식을 반환 할 수 없습니까? 를 읽어보십시오 . 정말? .

면책 조항 : 내가 링크 한 기사가 해결 방법을 보여 주지만 그것이 좋은 생각은 아닙니다. 일반 유형을 만드는 것이 더 안전하고 이해하기 쉬울 때이 방법을 사용하지 않는 것이 좋습니다.


또는 .NET 4.0 이상에서 Tuple 클래스를 사용할 수 있습니다.

http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx

Tuple<string, string> Create()
{
return Tuple.Create("test1", "test2");
} 

그런 다음 다음과 같은 속성에 액세스 할 수 있습니다.

var result = Create();
result.Item1;
result.Item2;

public object MyMethod() 
{
    return new
    {
         Property1 = "test",
        Property2 = "test"
     };
}

static void Main(..)
{
    dynamic o = MyMethod();  
    var p1 = o.Property1;
    var p2 = o.Property2;
}

가장 쉬운 해결책은 클래스를 만들고 값을 속성에 넣은 다음 반환하는 것입니다. 익명 유형이 삶을 더 어렵게 만든다면 올바르게 사용하지 않는 것입니다.


대안으로 C # 7부터 ValueTuple 을 사용할 수 있습니다 . 여기 에서 약간의 예 :

public (int sum, int count) DoStuff(IEnumerable<int> values) 
{
    var res = (sum: 0, count: 0);
    foreach (var value in values) { res.sum += value; res.count++; }
    return res;
}

그리고받는 쪽에서 :

var result = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {result.Sum}, Count: {result.Count}");

또는:

var (sum, count) = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {sum}, Count: {count}");

이것이 좋은 생각인지 아닌지에 대한 경고에도 불구하고 ... A dynamic는 사적인 방법으로 잘 작동 하는 것 같습니다.

void Main()
{
    var result = MyMethod();
    Console.WriteLine($"Result: {result.Property1}, {result.Property2}");
}

public dynamic MyMethod()
{
    return new { Property1 = "test1", Property2 = "test2" };
}

LinqPad 에서이 예제를 실행할 수 있습니다 . 다음과 같이 출력됩니다.

결과 : test1, test2


No, anonymous types cannot exist outside of the context in which they are created, and as a result cannot be used as a method return type. You can return the instance as an object, but it's a much better idea to explicitly create your own container type for this purpose.


I think Andrew Hare is right, you'd have to just return "object." For an editorial comment, I feel like dealing with raw objects in OO code can be a "code smell." There are cases where it's the right thing to do, but most of the time, you'd be better off defining an interface to return, or using some sort of base class type, if you're going to be returning related types.


Sorry, you really aren't supposed to do that. You can hack around it with reflection or by making a generic helper method to return the type for you, but doing so is really working against the language. Just declare the type so it's clear what's going on.


No, there is no support for expanding the scope of the anonymous class outside the method. Outside of the method the class is truly anonymous, and reflection is the only way to access it's members.


You could also invert your control flow if possible:

    public abstract class SafeAnon<TContext>
    {
        public static Anon<T> Create<T>(Func<T> anonFactory)
        {
            return new Anon<T>(anonFactory());
        }

        public abstract void Fire(TContext context);
        public class Anon<T> : SafeAnon<TContext>
        {
            private readonly T _out;

            public delegate void Delayed(TContext context, T anon);

            public Anon(T @out)
            {
                _out = @out;
            }

            public event Delayed UseMe;
            public override void Fire(TContext context)
            {
                UseMe?.Invoke(context, _out);
            }
        }
    }

    public static SafeAnon<SomeContext> Test()
    {
        var sa = SafeAnon<SomeContext>.Create(() => new { AnonStuff = "asdf123" });

        sa.UseMe += (ctx, anon) =>
        {
            ctx.Stuff.Add(anon.AnonStuff);
        };

        return sa;
    }

    public class SomeContext
    {
        public List<string> Stuff = new List<string>();
    }

and then later somwhere else:

    static void Main()
    {
        var anonWithoutContext = Test();

        var nowTheresMyContext = new SomeContext();
        anonWithoutContext.Fire(nowTheresMyContext);

        Console.WriteLine(nowTheresMyContext.Stuff[0]);

    }

참고URL : https://stackoverflow.com/questions/1329672/is-there-a-way-to-return-anonymous-type-from-method

반응형