2013-04-10 7 views
10

że ma przekazać tablicę dowolnych obiektów do funkcji jak String.Join który posiada następujące PODPISYPrzechodząc tablicę funkcji, która przyjmuje albo params Zadanie [] lub IEnumerable <T>

  • public static string Join(string separator, params Object[] values)
  • public static string Join(string separator, IEnumerable<T> values)

Gdybym wywołać funkcję tak:

var arr = new MyClass[]{ new MyClass(), new MyClass() }; 
string text = string.Join("\n", arr); 

otrzymuję błąd kompilatora:

The call is ambiguous between the following methods or properties: 'string.Join(string, params object[])' and 'string.Join(string, System.Collections.Generic.IEnumerable)'

mogę rozwiązać niejednoznaczność za pomocą funkcji IEnumerable<T>:

var arr = new MyClass[]{ new MyClass(), new MyClass() }; 
string text = string.Join<MyClass>("\n", arr); 

Ale mogę wywołać funkcję params object[]? W krytycznym scenariuszu wydajności lepiej byłoby uzyskać dostęp do tablicy bezpośrednio, niż przez moduł wyliczający.

Używam C# 4.0, jeśli to robi różnicę.

Odpowiedz

17

Jeśli zdać object[] jako drugi parametr, kompilator powinien wybrać przeciążenie object[] ponieważ dokładnie pasuje. W przypadku, gdy masz inaczej wpisany array (MyClass[] w tym przypadku) tylko rzutować tablicę object[]:

string.Join("\n", (object[])arr); 

Nie jesteś rzeczywiście się zmienia rodzaje dowolnych obiektów lub wykonywania żadnej konwersji w czasie wykonywania, ci” ponownie daje kompilatorowi wskazówkę dotyczącą tego, którego przeciążenia użyć.

Co do komentarza dotyczącego wydajności, nie zapomnij przetestować obu opcji, jeśli wydajność jest tak ważna. Nie zakładaj, że jeden jest szybszy od drugiego. (I zawsze profil całej aplikacji - jest prawdopodobne, że ewentualne zatory będą gdzie indziej.)

3

Jeśli zmienić typ zmiennej arr do object[] można nazwać drugą przeciążeniem:

object[] arr = new MyClass[] { new MyClass(), new MyClass() }; 
string text = string.Join("\n", arr); 

Możesz również jawnie rzucić go do object[]: string.Join ("\ n", (object []) arr);

0

Możesz zadzwonić do innego przeciążenie takiego (to co param są wykorzystywane do) -

string text = string.Join("\n", new MyClass(), new MyClass()); 
0

Najprostsza zmiana kodu byłoby, aby przejść od:

var arr = new MyClass[]{ new MyClass(), new MyClass() }; 
    string text = string.Join("\n", arr); 

Do:

var arr = new object[]{ new MyClass(), new MyClass() }; 
    string text = string.Join("\n", arr); 

Jak wspomniano wcześniej, odlewanie działa również:

var arr = new MyClass[]{ new MyClass(), new MyClass() }; 
    string text = string.Join("\n", (object[])arr); 

Aby uzyskać więcej informacji na ten temat, należy przeprowadzić analizę C# overload resolution.

Przeciążenie jest interesującym tematem, ale nie znalazłem jeszcze rozwiązania tego problemu.

+0

Jak wspomniałem w moim pytaniu, chcę przekazać tablicę do odpowiedniej implementacji mojej własnej funkcji (nie String.Join, ale coś z podobnymi sygnaturami metod). Różnice w wydajności wynikają z różnych implementacji mojej funkcji. Niektóre operacje, takie jak uzyskanie liczby elementów w kolekcji, są wykonywane szybciej przy użyciu tablicy niż "IEnumerable ". – bouvierr

+0

Metoda rozszerzenia Count() używa właściwości .Length w przypadku, gdy IEnumerable jest tablicą, ale nie o to ci chodzi. Możesz rozważyć użycie różnych nazw dla członków i nie polegać na rozdzielczości przeciążenia, jeśli różnica wydajności jest tak ważna. Dlatego nie będziesz musiał wymuszać typów kompilacji, aby uzyskać semantykę, której szukasz. – Doug

0

Jeśli urządzenie korzysta IEnumerable można użyć <object> rodzajowe przeciążenie metody ToArray():

var allFoos = foo.GetAllFoos().ToArray<object>(); 
string s = string.Join(", ", allFoos); 

Wygląda mniej nadęty i bardziej czytelne dla mnie.

Powiązane problemy