[C#] 익명 형식을 매개 변수로 전달하는 방법은 무엇입니까?

익명 유형을 매개 변수로 다른 함수에 전달하려면 어떻게해야합니까? 이 예제를 고려하십시오.

var query = from employee in employees select new { Name = employee.Name, Id = employee.Id };
LogEmployees(query);

여기서 변수 query는 강력한 유형이 없습니다. LogEmployees함수를 받아들이려면 어떻게 함수를 정의해야 합니까?

public void LogEmployees (? list)
{
    foreach (? item in list)
    {

    }
}

즉, ?마크 대신에 무엇을 사용해야합니까 ?



답변

이 익명 유형에 대한 수업을 만들어야한다고 생각합니다. 그것은 제 생각에 가장 현명한 일입니다. 그러나 정말로 원하지 않는다면 역학을 사용할 수 있습니다.

public void LogEmployees (IEnumerable<dynamic> list)
{
    foreach (dynamic item in list)
    {
        string name = item.Name;
        int id = item.Id;
    }
}

이 유형 은 강력하게 입력 되지 않으므로 예를 들어 이름이 EmployeeName으로 변경되면 런타임까지 문제가 있음을 알 수 없습니다.


답변

다음과 같이 할 수 있습니다 :

public void LogEmployees<T>(List<T> list) // Or IEnumerable<T> list
{
    foreach (T item in list)
    {

    }
}

…하지만 각 항목별로 많은 것을 할 수는 없습니다. 당신은 ToString을 호출 할 수 있지만 (예를 들어)를 사용할 수 없습니다 NameId직접.


답변

불행히도, 당신이하려는 것은 불가능합니다. 후드 아래에서 쿼리 변수는IEnumerable 익명 형식으로 입력됩니다. 익명 형식 이름은 사용자 코드로 표현할 수 없으므로 함수에 입력 매개 변수를 만들 방법이 없습니다.

최선의 방법은 유형을 작성하고이를 조회의 리턴으로 사용하여 함수에 전달하는 것입니다. 예를 들어

struct Data {
  public string ColumnName;
}

var query = (from name in some.Table
            select new Data { ColumnName = name });
MethodOp(query);
...
MethodOp(IEnumerable<Data> enumerable);

이 경우 단일 필드 만 선택하므로 필드를 직접 선택하는 것이 더 쉬울 수 있습니다. 그러면 IEnumerable필드 유형 으로 조회가 입력됩니다 . 이 경우 열 이름입니다.

var query = (from name in some.Table select name);  // IEnumerable<string>


답변

매개 변수 유형이이 아닌 경우 익명 유형을 일반이 아닌 함수에 전달할 수 없습니다 object.

public void LogEmployees (object obj)
{
    var list = obj as IEnumerable();
    if (list == null)
       return;

    foreach (var item in list)
    {

    }
}

익명 유형은 메소드 내에서 단기 사용을위한 것입니다.

MSDN에서- 익명 유형 :

필드, 속성, 이벤트 또는 메서드의 반환 형식을 익명 형식으로 선언 할 수 없습니다. 마찬가지로 메서드, 속성, 생성자 또는 인덱서의 형식 매개 변수를 익명 형식으로 선언 할 수 없습니다. 익명 형식 또는 익명 형식이 포함 된 컬렉션을 메서드의 인수로 전달하려면 매개 변수를 type object로 선언하면됩니다 . 그러나 이렇게하면 강력한 타이핑의 목적이 무효가됩니다.

(강조 광산)


최신 정보

제네릭을 사용하여 원하는 것을 얻을 수 있습니다.

public void LogEmployees<T>(IEnumerable<T> list)
{
    foreach (T item in list)
    {

    }
}


답변

일반적으로 다음과 같이 제네릭을 사용하여이 작업을 수행합니다.

MapEntToObj<T>(IQueryable<T> query) {...}

그런 다음 컴파일러는 T호출 할 때 를 유추해야합니다 MapEntToObj(query). 메소드 내부에서 무엇을하고 싶은지 잘 모르겠으므로 이것이 유용한 지 여부를 알 수 없습니다 … 문제는 MapEntToObj여전히 내부에서 이름을 지정할 수 없다는 T것입니다.

  • 다른 일반적인 메소드를 호출 T
  • 에 반사를 사용 T하여 일을

그러나 그 외에는 익명 유형을 조작하는 것이 매우 어렵습니다.

데이터 를 추출 할 때의 또 다른 트릭 은 선택기를 전달하는 것입니다.

Foo<TSource, TValue>(IEnumerable<TSource> source,
        Func<TSource,string> name) {
    foreach(TSource item in source) Console.WriteLine(name(item));
}
...
Foo(query, x=>x.Title);


답변

다음 트릭으로 익명을 사용할 수 있습니다 (익명 유형으로 캐스트).

public void LogEmployees<T>(IEnumerable<T> list)
{
    foreach (T item in list)
    {
        var typedItem = Cast(item, new { Name = "", Id = 0 });
        // now you can use typedItem.Name, etc.
    }
}

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


답변

“동적”도이 목적으로 사용될 수 있습니다.

var anonymousType = new { Id = 1, Name = "A" };

var anonymousTypes = new[] { new { Id = 1, Name = "A" }, new { Id = 2, Name = "B" };

private void DisplayAnonymousType(dynamic anonymousType)
{
}

private void DisplayAnonymousTypes(IEnumerable<dynamic> anonymousTypes)
{
   foreach (var info in anonymousTypes)
   {

   }
}