Из списка <object>, ToString () их только тогда, когда они являются примитивными типами или этот метод переопределен - PullRequest
1 голос
/ 15 февраля 2011

Учитывая список объектов, я хотел бы напечатать их строковую версию на тот случай, если результат object.ToString () является релевантной строкой.

Я имею в виду, что не хочучтобы получить такие вещи, как:

obj.ToString() -> System.Collections.Generic.List`1[MyLib.Dude]  
obj.ToString() -> System.Collections.Generic.Dictionary`2[System.Int32,System.DateTime]
obj.ToString() -> System.Byte[]

Но я хочу получить такие вещи:

obj.ToString() -> Hi
obj.ToString() -> 129847.123
obj.ToString() -> Id = 123

Каким должен быть лучший способ реализовать это в методе:

Public Sub PrintInterestingStuffOnly(ByVal coolList as Ilist(Of Object))
    For Each obj in coolList
        'insert solution here
        Console.WriteLine( ....
    End For
End Sub

Ответы [ 3 ]

3 голосов
/ 15 февраля 2011
var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
foreach (var item in coolList)
{
    Type t = item.GetType();
    if (t.IsPrimitive
        || (t.GetMethod("ToString", bf, null, Type.EmptyTypes, null) != null))
    {
        Console.WriteLine(item);
    }
}

Это может быть медленно, так как он использует отражение, чтобы определить, переопределил ли конкретный тип метод ToString.Более быстрой альтернативой может быть использование статического кэша для «запоминания» результата отражения, так что его нужно делать только один раз для каждого типа:

foreach (var item in coolList)
{
    Type t = item.GetType();
    if (t.IsPrimitive || _cache.GetOrAdd(t, _factory))
    {
        Console.WriteLine(item);
    }
}

// ...

private static readonly ConcurrentDictionary<Type, bool> _cache =
    new ConcurrentDictionary<Type, bool>();

private const BindingFlags _flags =
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

private static readonly Func<Type, bool> _factory =
    t => t.GetMethod("ToString", _flags, null, Type.EmptyTypes, null) != null;
2 голосов
/ 15 февраля 2011
string.Join(", ", list);

Если список был составлен из { 1, 2, 3, 4 }, будет напечатано:

1, 2, 3, 4

(Он будет выполнять .ToString() неявно, поэтому вы можете использовать любой вид объекта.)

0 голосов
/ 15 февраля 2011
If Not obj.ToString().StartsWith("System.") Then 
...