C# 在C语言中将字符串转换为泛型类型(基本或数组)#

C# 在C语言中将字符串转换为泛型类型(基本或数组)#,c#,generics,type-conversion,C#,Generics,Type Conversion,我想将字符串转换为给定的泛型类型T。它可以是基本类型或字符串(例如int或string),也可以是基本类型或字符串的数组(例如int[]或string[])。我有以下功能: T Str2Val<T>(string str) { return (T)Convert.ChangeType(str, typeof(T)); } 或者实现两个重载函数:一个用于泛型T,另一个用于泛型E[]。然而,这两种解决方案都失败了。我不能在else子句中使用任何特定于数组的代码,因为它必须与标量兼容

我想将字符串转换为给定的泛型类型
T
。它可以是基本类型或字符串(例如
int
string
),也可以是基本类型或字符串的数组(例如
int[]
string[]
)。我有以下功能:

T Str2Val<T>(string str)
{
  return (T)Convert.ChangeType(str, typeof(T));
}
或者实现两个重载函数:一个用于泛型
T
,另一个用于泛型
E[]
。然而,这两种解决方案都失败了。我不能在else子句中使用任何特定于数组的代码,因为它必须与标量兼容。当
T
实际上是一个数组时,C#无法使用
E[]
选择适当的重载


我该怎么办?

我会创建一些自定义解析器的列表,您可以注册这些解析器,然后在以后利用它们,因为您似乎仍然希望使用自定义规则:

public static class StringParsers
{
    private static Dictionary<Type, object> Parsers = new Dictionary<Type, object>();

    public static void RegisterParser<T>(Func<string, T> parseFunction)
    {
        Parsers[typeof(T)] = parseFunction;
    }

    public static T Parse<T>(string input)
    {
        object untypedParser;
        if (!Parsers.TryGetValue(typeof(T), out untypedParser))
            throw new Exception("Could not find a parser for type " + typeof(T).FullName);

        Func<string, T> parser = (Func<string, T>)untypedParser;

        return parser(input);
    }
}

但这感觉很不对。一定有更好的方法避免Alexander答案中的双重通用输入,但你可以这样做。

也许类似的方法会有所帮助:

dynamic Str2Val<T>(string str)
{
    if (!typeof(T).IsArray)
        return (T)Convert.ChangeType(str, typeof(T));

    var elementType = typeof(T).GetElementType();
    return str.Split(',').Select(x => Convert.ChangeType(x, elementType)).ToArray();
}
动态Str2Val(字符串str)
{
如果(!typeof(T).IsArray)
return(T)Convert.ChangeType(str,typeof(T));
var elementType=typeof(T).GetElementType();
返回str.Split(',')。选择(x=>Convert.ChangeType(x,elementType)).ToArray();
}

另一个具有显式元素类型传递的解决方案:

static T Str2Val<T>(string str)
{
    return (T)Convert.ChangeType(str, typeof(T));
}

static E[] Str2Val<T, E>(string str)
    where T : ICollection<E>
{
    return str.Split(',').Select(x => (E)Convert.ChangeType(x, typeof(E))).ToArray();
}
static T Str2Val(string str)
{
return(T)Convert.ChangeType(str,typeof(T));
}
静态E[]Str2Val(字符串str)
其中T:i收集
{
返回str.Split(',')。选择(x=>(E)Convert.ChangeType(x,typeof(E))).ToArray();
}
使用

Str2Val(“1”)
Str2Val(“1,3”)

如何将字符串转换为数组,以及转换为什么的数组<代码>字符[]?使用
tocharray
<代码>int[]?如何拆分:逗号、破折号、点?我不想将字符串转换为数组。字符串应转换为字符串(即无更改)。字符串数组现在对我的任务很感兴趣,所以任何拆分都是可以接受的。数字数组应该用逗号表示。那么您是否正在尝试将
int[]
转换为
string
?不,对于
T==int[]
我正在尝试将
string
转换为
int[]
,比如
“1,2,3”
转换为
{1,2,3}
。您应该检查
T
是否实现了
IConvertible
。否则,使用
Convert.ChangeType
就不可能成功。您可以这样做:
if(typeof(IConvertible).IsAssignableFrom(typeof(T)){return(T)Convert.ChangeType(str,typeof(T));}/*否则,检查T是否是集合,依此类推*/
。这将转换为
对象[]
,而不是
E[]
。是否确定转换
(Func)为非类型ParserT
是一个数组,那么code>是可能的吗?@Mikhail是的,上面的代码已经过测试并正常工作<当调用时,code>T已经是type(例如)
int[]
。好的,我认为这是一个有效的解决方案。虽然与我最初的单行函数相比,仅仅处理数组的代价确实很高。不管怎样,谢谢你。@Mikhail我添加了一个带有一体式功能的编辑,但我不喜欢它。:)(也测试和工作)我的上帝,它工作!我不知道为什么
(T)(object)
有效,而
(T)
无效,但这正是我需要的!这是我唯一认为不可能的事。谢谢!不错,但它需要更改
Str2Val
的接口和代码复制。
string testArrayInput = "1,2,8";

int[] integers = StringParsers.Parse<int[]>(testArrayInput); // {1, 2, 8}

string[] strings = StringParsers.Parse<string[]>(testArrayInput); // {"1", "2", "8"}

int singleInt = StringParsers.Parse<int>("9999"); //9999
public static T Str2Val<T>(string str)
{
    if (!typeof(T).IsArray)
        return (T)Convert.ChangeType(str, typeof(T));

    Type elementType = typeof(T).GetElementType();

    string[] entries = str.Split(',');
    int numberOfEntries = entries.Length;

    System.Array array = Array.CreateInstance(elementType, numberOfEntries);

    for(int i = 0; i < numberOfEntries; i++)
        array.SetValue(Convert.ChangeType(entries[i], elementType), i);

    return (T)(object)array;
}
dynamic Str2Val<T>(string str)
{
    if (!typeof(T).IsArray)
        return (T)Convert.ChangeType(str, typeof(T));

    var elementType = typeof(T).GetElementType();
    return str.Split(',').Select(x => Convert.ChangeType(x, elementType)).ToArray();
}
static T Str2Val<T>(string str)
{
    return (T)Convert.ChangeType(str, typeof(T));
}

static E[] Str2Val<T, E>(string str)
    where T : ICollection<E>
{
    return str.Split(',').Select(x => (E)Convert.ChangeType(x, typeof(E))).ToArray();
}
Str2Val<int>("1")
Str2Val<int[], int>("1,3")