微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在将非数组和数组都用作类的通用类型参数的同时,将字符串数组转换为通用数组类型?

如何解决如何在将非数组和数组都用作类的通用类型参数的同时,将字符串数组转换为通用数组类型?

我有一个Option<T>,它非常适合从字符串转换的任何类型,现在我试图将其扩展到Option<T[]>(即Option<int[]>))。由于太多的C ++模板,我遇到了这个问题。把头缠在看似不足的C#泛型上时遇到了麻烦。我可以检测到T是一个数组,但是后来我无法使用typeof(T).GetElementType()

我认为我可能正处在XY问题谷之一,我只是从错误的方向来此,看不到上升的路径。有什么想法可以使自己不受限制吗?我已经尝试了所有我能想到的一切,并在过去的几天中尝试找出不受阻碍的地方。 我要补充一点,在转换之前,我可以安排将逗号分隔的字符串解析为字符串数组。下面的代码是我尝试过的一些内容的简化摘录。

using System;
using System.Collections.Generic;

namespace StackOverflowCS
{
    internal static class ConversionExtensionMethods
    {
        internal static T ChangeType<T>(this object obj)
        {
            try
            {
                return (T)Convert.ChangeType(obj,typeof(T));
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        internal static T ChangeType<T>(this object[] objects)
        {
            try
            {
                if (!typeof(T).IsArray) throw new Exception("T is not an array type.");

                var converted = new object[objects.Length];

                foreach (var item in objects)
                {
                    // AFAIK,converstion requires compile time kNowledge of T.GetElementType(),// but this won't compile.
                    converted.Add(item.ChangeType<typeof(T).GetElementType())>
                }

                return (T)converted; // And this won't compile either.
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
    }


    internal class Option<T>
    {
        public T Value;

        public Option() {}

        // This works fine for non-arrays
        public bool SetValue(string valueString)
        {
            try
            {
                Value = valueString.ChangeType<T>();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return false;
            }

            return true;
        }

        // I think I am in an XY problem valley here.
        public bool SetValue(string[] valueStrings)
        {
            try
            {
                if (!typeof(T).IsArray)
                {
                    throw new Exception("T is not an array type.");
                }

                // The crux of my problem is I can't seem to write pure generic code in C#
                var convertedElements = new List<!!!Cannot use typeof(T).GetElementType() here!!!>();

                foreach (var item in valueStrings)
                {
                    // The crux of my problem is I can't seem to write pure generic code in C#
                    convertedElements.Add(!!!Cannot use typeof(T).GetElementType() here!!!);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return false;
            }

            return true;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            var opt = new Option<int>(); // Works fine.

            var integerList = new Option<int[]>();

            integerList.SetValue("this,that,whatever"); // This fails at run-time.

            foreach (var item in integerList.Value)
            {
                Console.WriteLine(item);
            }


            Console.ReadKey();
        }
        
    }
}

解析器(未显示)可以检测以下形式的参数
Opt:1,2,3
Opt:"short sentence",word,"string with quotes\" in it"等。
我宁愿没有解析器尝试找出Opt Option的数组元素是什么类型。 Option<T>.SetValue(string[] strings)函数应该能够处理该问题。
我什至没有尝试过测试/实现`Options ,尽管我怀疑这样做会容易得多。

解决方法

您可以尝试这样做以允许同时使用非数组和数组通用类型参数:

using System;
using System.Linq;

SetValue(字符串值字符串)

public bool SetValue(string valueString)
{
  try
  {
    if ( typeof(T).IsArray ) throw new Exception("T is an array type.");
    Value = (T)Convert.ChangeType(valueString,typeof(T));
  }
  catch ( Exception e )
  {
    Console.WriteLine(e);
    return false;
  }
  return true;
}

SetValue(string [] valueStrings)

public bool SetValue(string[] valueStrings)
{
  try
  {
    if ( !typeof(T).IsArray ) throw new Exception("T is not an array type.");
    var thetype = typeof(T).GetElementType();
    var list = valueStrings.Select(s => Convert.ChangeType(s,thetype)).ToList();
    var array = Array.CreateInstance(thetype,list.Count);
    for (int index = 0; index < list.Count; index++ )
      array.SetValue(list[index],index);
    Value = (T)Convert.ChangeType(array,typeof(T));
  }
  catch ( Exception e )
  {
    Console.WriteLine(e);
    return false;
  }
  return true;
}

测试

static void Main(string[] args)
{
  // Non array
  var opt = new Option<int>();
  opt.SetValue("10");
  Console.WriteLine(opt.Value);
  Console.WriteLine();
  // Array
  var integerList = new Option<int[]>();
  integerList.SetValue(new[] { "1","2","3" });
  foreach ( var item in integerList.Value )
    Console.WriteLine(item);
  // End
  Console.ReadKey();
}

输出

10

1
2
3

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。