development

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

big-blog 2020. 7. 9. 07:49
반응형

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


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

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) {...}

The compiler should then infer the T when you call MapEntToObj(query). Not quite sure what you want to do inside the method, so I can't tell whether this is useful... the problem is that inside MapEntToObj you still can't name the T - you can either:

  • call other generic methods with T
  • use reflection on T to do things

but other than that, it is quite hard to manipulate anonymous types - not least because they are immutable ;-p

Another trick (when extracting data) is to also pass a selector - i.e. something like:

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

You can use generics with the following trick (casting to anonymous type):

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;
}

"dynamic" can also be used for this purpose.

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)
   {

   }
}

Instead of passing an anonymous type, pass a List of a dynamic type:

  1. var dynamicResult = anonymousQueryResult.ToList<dynamic>();
  2. Method signature: DoSomething(List<dynamic> _dynamicResult)
  3. Call method: DoSomething(dynamicResult);
  4. done.

Thanks to Petar Ivanov!


If you know, that your results implements a certain interface you could use the interface as datatype:

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

    }
}

I would use IEnumerable<object> as type for the argument. However not a great gain for the unavoidable explicit cast. Cheers

참고URL : https://stackoverflow.com/questions/6624811/how-to-pass-anonymous-types-as-parameters

반응형