C# 泛型方法检测 T 是否为数组,然后索引到数组中

问题描述 投票:0回答:1

我正在尝试编写一个

Dbg
调试函数,它将打印出有关给定参数的一些调试信息,然后返回它。我希望将数组打印为元素列表,并使用
.ToString()
打印标量。到目前为止我已经:


public static class Utils
{
    /// <summary>
    /// Log the given expression to the console iff a debugger is attached,
    /// returning that same value transparently. Useful for debugging values
    /// without rewriting all your code. Also logs the caller and line
    /// number via compiler trickery.
    /// </summary>
    public static T Dbg<T>(
        T thingToLog,
        // Ask the compiler to insert the current file, line number, and caller
        [CallerFilePathAttribute] string filepath = null,
        [CallerLineNumber] int lineNumber = 0,
        [CallerMemberName] string caller = null
    )
    {
        if (System.Diagnostics.Debugger.IsAttached)
        {
            string filename = filepath.Split('\\').Last();
            // FIXME This doesn't actually print the array, just "System.Byte[]" or similar
            string stringToLog = typeof(T).IsArray ? "[ " + String.Join(", ", thingToLog) + " ]" : thingToLog.ToString();
            Console.WriteLine($"[{filename}:{lineNumber} {caller}()] {stringToLog}");
        }
        return thingToLog;
    }
}

问题出在这一行:

string stringToLog = typeof(T).IsArray ? "[ " + String.Join(", ", thingToLog) + " ]" : thingToLog.ToString();

它只输出

thingToLog
的类型,就像
System.Byte[]
一样,但我希望它输出字节数组中的元素。在调试器中,尝试访问
thingToLog
的元素会导致
thingToLog[0]   error CS0021: Cannot apply indexing with [] to an expression of type 'T'
,这很公平。但是如果我尝试转换为
object[]
,那么我会得到
((object[])thingToLog)[0]    error CS0030: Cannot convert type 'T' to 'object[]'. And if I try first cast to an 
object
and then to an
object[]
, I get 
'((object[])((object)thingToLog))[0]' 抛出异常输入“System.InvalidCastException”`

是否可以检测

T
是否可枚举,如果是,则枚举要打印的元素?

c# arrays types
1个回答
0
投票

为了解决这个问题,可以使用反射来处理不同类型的集合和数组。我提供了“Dbg”函数的更新版本,它可以正确处理数组和其他可枚举类型。

using System;
using System.Collections;
using System.Linq;
using System.Runtime.CompilerServices;

public static class Utils
{
public static T Dbg<T>(
    T thingToLog,
    [CallerFilePath] string filepath = null,
    [CallerLineNumber] int lineNumber = 0,
    [CallerMemberName] string caller = null
)
{
    if (System.Diagnostics.Debugger.IsAttached)
    {
        string filename = filepath.Split('\\').Last();
        string stringToLog;

        if (thingToLog is IEnumerable enumerable && !(thingToLog is string))
        {
            var elements = enumerable.Cast<object>().Select(e => e?.ToString() ?? "null");
            stringToLog = "[ " + string.Join(", ", elements) + " ]";
        }
        else
        {
            stringToLog = thingToLog?.ToString() ?? "null";
        }

        Console.WriteLine($"[{filename}:{lineNumber} {caller}()] {stringToLog}");
    }
    return thingToLog;
}
}

希望这会有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.