문제

이걸 고려하세요:

var me = new { FirstName = "John", LastName = "Smith" };

그런 다음이 작업을 수행 할 수 있으므로 괜찮습니다.

Console.WriteLine("{0} {1}", me.FirstName, me.LastName);

그러나 우리는 이것을 할 수 없습니다 :

public T GetMe()
{
    return new { FirstName = "John", LastName = "Smith" };
}

우리는 T의 유형을 모르기 때문에.

우리는 이것을 할 수 있습니다 :

public object GetMe()
{
    return new { FirstName = "John", LastName = "Smith" };
}

그러나 액세스하기 위해 반사를 사용하여 물체의 특성을 검사해야합니다.

var p = new Prog();
object o = p.GetMe();
Type t = o.GetType();
foreach (var prop in t.GetProperties())
{
    Console.WriteLine(prop.Name + ": " + prop.GetValue(o, null));
}

그러나 익명 유형의 이름을 정의 할 수 있다면 어떨까요? 물론 그것은 더 이상 익명이 아니지만 정상적인 클래스 정의보다 간결하고 유지 가능할 것입니다.

이걸 고려하세요:

public Person GetMe()
{
    return new public class Person { FirstName = "John", LastName = "Smith" };
}

그런 다음 이점은 클래스를 명시 적으로 정의 할 필요없이 방법에서 복잡한 LINQ 쿼리의 결과를 반환 할 수 있다는 것입니다.

이 비교적 복잡한 LINQ 쿼리를 고려하십시오.

List<int> list = new List<int>();
var query = from number in list
            select
                new
                    {
                        Number = number,
                        Square = number*number,
                        Absolute = Math.Abs(number),
                        Range = Enumerable.Range(0, number)
                    };

그렇게 클래스를 정의하는 대신 :

public class MyNumbers
{
    public int Number { get; set; }
    public int Square { get; set; }
    public int Absolute { get; set; }
    public IEnumerable<int> Range { get; set; }
}

메소드에서 쿼리 변수를 반환하려면 대신 다음을 수행 할 수 있습니다.

List<int> list = new List<int>();
return from number in list
            select new public class MyNumbers
                    {
                        Number = number,
                        Square = number*number,
                        Absolute = Math.Abs(number),
                        Range = Enumerable.Range(0, number)
                    };
도움이 되었습니까?

해결책

실제로, 메소드에서 익명 유형을 다시 얻기 위해 할 수있는 "해킹"이 있습니다. 이걸 고려하세요:

public object MyMethod()
    {
        var myNewObject = new
        {
            stringProperty = "Hello, World!",
            intProperty = 1337,
            boolProperty = false
        };

        return myNewObject;
    }

    public T Cast<T>(object obj, T type)
    {
        return (T)obj;
    }

이제 다음을 수행 할 수 있습니다.

var obj = MyMethod();
var myNewObj = Cast(obj, new { stringProperty = "", intProperty = 0, boolProperty = false });

MyNewobj는 이제 익명 유형과 동일한 유형의 객체가 될 것입니다.

다른 팁

필요한 언어 기능은 다음과 같습니다.

public var GetMe()
{
    return new { FirstName = "John", LastName = "Smith" };
}

그건, var 메소드 리턴 유형으로 유효하며 컴파일러는 반환 된 내용의 실제 유형을 유추합니다. 그런 다음 전화 사이트 에서이 작업을 수행해야합니다.

var me = GetMe();

동일한 유형의 구성원이있는 두 가지 익명 유형은 동일한 유형이므로 동일한 패턴을 반환하는 다른 기능을 작성하면 동일한 유형을 가질 것입니다. B가 A의 구성원의 서브 세트를 갖는 모든 유형 A 및 B의 경우, A는 B와 할당 대응 가능하다 (B는 A의 기본 클래스와 같습니다). 당신이 쓴 경우 :

public var GetMeFrom(var names)
{
    return new { FirstName = names["First"], LastName = names["Last"] };
}

컴파일러는 이것을 두 가지 유형 매개 변수를 가진 일반적인 방법으로 효과적으로 정의합니다. T1 이름의 유형입니다 T2 인덱서에 의해 반환 된 유형입니다 T1 그것은 문자열을 받아들입니다. T1 문자열을 수용하는 인덱서가 있어야하므로 제한됩니다. 그리고 통화 사이트에서는 문자열을 수락하고 반환 한 인덱서가있는 모든 것을 전달합니다. 당신이 좋아하는 모든 유형, 그리고 그것은 유형을 결정합니다 FirstName 그리고 LastName 반환 된 유형에서 GetMeFrom.

따라서 Toxtenference는 코드에서 발견 할 수있는 모든 유형 제약 조건을 자동으로 캡처합니다.

IMHO 근본 문제는 익명 유형과 관련이 없지만 클래스를 선언하는 것은 너무 장점입니다.

옵션 1:

다음과 같은 수업을 선언 할 수 있다면 :

public class MyClass
{ properties={ int Number, int Square, int Absolute, IEnumerable<int> Range } }

또는 튜플 예와 같이 다른 유사한 빠른 방법 (튜플 예와 같이)은 코드를 저장하기 위해 익명 유형으로 해킹 할 필요가 없을 것입니다.

'서비스로서의 컴파일러'가 C#5에 도착하면,이를 통합하는 데 좋은 작업을 수행하고 메타 프로 그램을 사용하여 이러한 종류의 문제를 깨끗하게 해결할 수 있기를 바랍니다. 파티는 1958 년입니다!

Option 2:

또는 C#4에서는 익명 유형을 다음과 같이 전달할 수 있습니다. dynamic 그리고 모든 캐스팅을 피하십시오. 물론 변수의 이름을 바꾸는 경우 런타임 오류가 발생합니다.

옵션 3 : : 옵션 3.

C#이 C ++와 같은 방식으로 제네릭을 구현한다면 익명 유형을 메소드로 전달할 수 있고 올바른 멤버가있는 한 컴파일됩니다. 정적 유형 안전의 모든 이점과 다운 사이드는 없습니다. 내가 입력해야 할 때마다 where T : ISomething C#에서 나는 그들이 이것을하지 않았다는 것이 화가났다!

당신이 설명하는 내용 (익명 유형)은 기본적으로 "튜플 유형"입니다.

나는 그들이 C#에 좋은 추가 일 것이라고 생각합니다.

C#에 대한 그러한 기능을 설계하고 있다면 다음과 같은 구문을 사용하여 노출시킵니다.

tuple<int x, int y>

할 수 있도록 :

public tuple<int x, int y> GetStuff()
{
}

그런 다음 익명 유형의 정의를 변경하여 다음과 같습니다.

new { x = 2, y = 2}

가졌다 tuple<int x, int y> 익명 유형이 아닌 유형으로.

현재 CLR과 함께 작동하도록하는 것은 약간 까다로울 수 있습니다. 일단 공개 서명에서 익명 유형을 지명 할 수 있으므로 별도로 편집 된 어셈블리를 통합 할 수 있어야합니다. 튜플 유형을 사용하는 어셈블리 내부에 "모듈 생성자"를 포함시켜 달성 할 수 있습니다. 보다 이 게시물 예를 들어.

이 접근법의 유일한 단점은 유형 생성에 대한 CLR의 "게으른"모델을 존중하지 않는다는 것입니다. 즉, 많은 독특한 튜플 유형을 사용하는 어셈블리는 약간 느린 하중 유형을 경험할 수 있습니다. 더 나은 접근 방식은 CLR에 직접 튜플 유형에 대한지지를 추가하는 것입니다.

그러나 CLR을 변경하는 것 외에도 모듈 생성자 접근 방식이 이와 같은 작업을 수행하는 가장 좋은 방법이라고 생각합니다.

나는이 기능을 좋아할 것입니다. 내가 이것을 원했던 여러 번있었습니다.

좋은 예는 XML을 처리하는 것입니다. 당신은 그들에게 객체를 되찾아 주지만, 발신자에게 다시 보내려면 구체적인 개체 버전을 만들어야합니다. 여러 번 당신은 상당히 변경되는 XML을 얻고 그것을 처리하기 위해 많은 수업을해야합니다. linqtoxml을 VAR로 사용하여 객체를 만들 수 있다면 반품하는 것이 좋지 않습니까?

나는 이것이 튜플을위한 멋진 컴파일러 마법 일 것이라고 생각합니다.

튜플 생성 :

(int, string, Person) tuple = (8, "hello", new Person());

동등한 :

Tuple<int,string,Person> tuple = new Tuple<int,string,Person>(8 ,"hello", new Person());

함수에서 :

public (int, string, Person) GetTuple(){
    return ...
}

가치 얻기 :

int number = tuple[1];
string text = tuple[2];
Person person = tuple[3];

속성 FirstName 및 LastName과의 인터페이스를 만들어 사용할 수 있습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top