【问题标题】:Constructor on type not found未找到类型的构造函数
【发布时间】:2014-10-24 00:22:53
【问题描述】:

异常消息:Constructor on type StateLog not found

我有以下代码不适用于一个类:

        List<T> list = new List<T>();
        string line;
        string[] lines;

        HttpWebResponse resp = (HttpWebResponse)HttpWebRequest.Create(requestURL).GetResponse();

        using (var reader = new StreamReader(resp.GetResponseStream()))
        {
            while ((line = reader.ReadLine()) != null)
            {
                lines = line.Split(splitParams);
                list.Add((T)Activator.CreateInstance(typeof(T), lines));
            }
        }

它不适用的类的构造函数与它适用的其他类完全相同。唯一的区别是这个类将传递 16 个参数而不是 2-5 个。构造函数如下所示:

    public StateLog(string[] line)
    {
        try
        {
            SessionID = long.Parse(line[0]);
            AgentNumber = int.Parse(line[1]);
            StateIndex = int.Parse(line[5]);
            ....
        }
        catch (ArgumentNullException anex)
        {
            ....
        }
    }

就像我说的,它适用于使用它的其他 5 个类,唯一的区别是输入的数量。

【问题讨论】:

  • 更严肃地说,也许您应该花一些时间告诉我们它是如何不起作用的。错误信息?
  • StateLog 类在该范围内是否可见?它有额外的构造函数重载吗?
  • 我认为问题标题的错误消息足以推断问题。会更新。
  • 它发生的那一行将使这个问题变得更好。依靠调用者来确保数组具有正确的长度,并且在该数组的正确位置包含可解析为正确类型的项目,这会导致代码容易出错。有通用的,也有危险的。这种方法很危险。我保证到明天,或者也许是后天,你就会忘记它是如何工作的。任何其他进入此代码的人都会迷路。 IMO,将数组作为参数传递是非常危险的。
  • 您的构造函数不接受 16 个参数,而只接受一个 string[] 类型的参数。

标签: c# constructor constructor-exception


【解决方案1】:

那是因为您使用的是Activator.CreateInstance overload,它接受一个对象数组,该数组应该包含一个构造函数参数列表。换句话说,它试图找到一个StateLog 构造函数重载,它有16 个参数,而不是一个。这是由于array covariance而编译的。

所以当编译器看到这个表达式时:

Activator.CreateInstance(typeof(T), lines)

由于linesstring[],它假定您希望依靠协方差将其自动转换为object[],这意味着编译器实际上是这样看待它的:

Activator.CreateInstance(typeof(T), (object[])lines)

然后该方法将尝试找到一个构造函数,该构造函数的参数数量等于lines.Length,所有类型均为string

例如,如果你有这些构造函数:

class StateLog
{
      public StateLog(string[] line) { ... }
      public StateLog(string a, string b, string c) { ... }
}

调用Activator.CreateInstance(typeof(StateLog), new string[] { "a", "b", "c" }) 将调用第二个构造函数(具有三个参数的那个),而不是第一个。

您真正想要的是将整个lines 数组作为第一个数组项 有效地传递:

var parameters = new object[1];
parameters[0] = lines;
Activator.CreateInstance(typeof(T), parameters)

当然,您可以简单地使用内联数组初始化器:

list.Add((T)Activator.CreateInstance(typeof(T), new object[] { lines }));

【讨论】:

  • 那么它对我的其他接受string[]作为构造函数参数的类是如何工作的?
  • 这些类是否有不同的接受更多参数的 ctor 重载?没什么,该方法只是寻找一个匹配的构造函数(其中参数的数量和它们的类型必须匹配)。
  • 它有一个接受16个string参数的重载? :)
  • 我明白你现在在说什么。它的参数数量很重要。如果我的睡眠时间超过 3 小时,我可能会早点得到。
  • 注意不是数组的类型。例如,如果您使用 Linq,请确保转换 .ToArray()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 2010-12-12
  • 2013-04-22
  • 1970-01-01
相关资源
最近更新 更多