【问题标题】:Setting array values without knowing its type在不知道其类型的情况下设置数组值
【发布时间】:2009-11-17 04:32:28
【问题描述】:

我在一个类似于下面设置的对象中有一个 MyType 数组,我希望能够按原样设置 myObject 上的索引值,我无法更改 MyFunction 的声明。

/*...*/
MyType [] myTypedArray = new MyType[100];
MyFunction(myTypedArray);
/*...*/

function MyFunction(object myObject)
{
    myObject[0] = new MyType();
}

这显然是行不通的,但我不知道如何让它工作。我不能使用模板/泛型它必须全部使用反射。

请注意,最初我必须将 myObjectArray 作为“对象”,因为这是我接收它的方式。我无法对对象 [] 进行初始转换。我已经尝试将 myObjectArray 转换为 object[] 并且它不起作用。

我也无法将 MyType 作为静态类型访问,只能访问运行时。

任何建议都会很棒,谢谢。

【问题讨论】:

  • 没有类型怎么new()呢?

标签: c# .net reflection


【解决方案1】:

myObjectArray 声明为objects 的数组:

object[] myObjectArray = myTypedArray;
myObjectArray[0] = new MyType(); // okay to go!

或者,如果出于某种原因myObjectArray 必须是object,您可以说:

((object[])myObjectArray)[0] = new MyType();

不过这些都很臭。并提防array covariance in C#

这是您似乎正在寻找的实现方式:

void AddToArray(object array, int index) {
    if(array == null) {
        throw new ArgumentNullException();
    }
    Type arrayType = array.GetType();
    if(!arrayType.IsArray) {
        throw new InvalidOperationException("array must be an Array");
    }

    (Array)asArray = (Array)array;
    if (index < 0 || index >= asArray.Length) {
        throw new ArgumentOutOfRangeException("index");
    }
    object newInstance = Activator.CreateInstance(elementType);
    asArray.SetValue(newInstance, index);
}

调用为:

AddToArray(myObjectArray, 0);

这假设elementType 有一个无参数的构造函数。有一些方法可以解决这个问题,但这应该足以让你开始。这个方法可能还需要一个更好的名字。

同样,这段代码很臭。我建议您退后一步,看看您是否可以使用强类型代码解决您的问题。

【讨论】:

  • 我已经澄清了问题,我无法控制我最初看到 myObjectArray 的方式 - 它作为对象而不是对象 []
  • @Chris:请参阅以“或者,如果出于某种原因...”开头的评论。
  • 谢谢杰森。但是我尝试了类似的方法,但出现错误“无法将'System.Boolean []'类型的对象转换为'System.Object []'类型。”
  • @Chris:是的,那是因为bool 是一个值类型。 CLR 绝不会让您将元素为值类型的数组转换为任何其他数组类型。所以string[] strings = new string[n]; object o = strings; object[] array = (object[])o; 是合法的,但bool[] bools = new bool[n]; object o = bools; object[] array = (object[])o; 是不合法的。
  • 知道我能做什么吗?数组类型可以是什么? (注意这是我自己的序列化内容)
【解决方案2】:

您可以将对象转换为Array 并在其上调用SetValue,这是一种完全非对象特定的方法。这将根据需要对值类型进行装箱和拆箱,并进行所有必要的数组类型检查。

【讨论】:

    【解决方案3】:

    尝试类似:

    DayOfWeek[] myTypedArray = Enum.GetValues(typeof(DayOfWeek))
                                   .OfType<DayOfWeek>().ToArray();
    object myObject = myTypedArray;
    
    object[] myObjectArray =   // from object to object[]
            (myObject as Array ?? new object[0]).OfType<object>().ToArray();
    
    Type type = myObjectArray[0].GetType(); // unbox type
    myObjectArray[0] = Activator.CreateInstance(type); // create another instance
    

    请注意,您将失去类型安全性。

    【讨论】:

      【解决方案4】:

      在这种情况下,您需要转换为object[]

      ((object[])myObjectArray)[0] = new MyType();
      

      【讨论】:

      • OP 说他不能投射到 object[]
      【解决方案5】:

      ((MyType[])myObjectArray)[0] = new MyType(); 或许?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-13
        • 1970-01-01
        • 2012-09-19
        • 2016-05-18
        • 2013-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多