构造函数链接

时间:2010-01-20 03:27:09

标签: c# .net

示例代码:

public class CA
{
    public CA(string s, List<int> numList)
    {
        // do some initialization
    }

    public CA(string s, int num) : this(s, ListHelper.CreateList(num))
    {
    }
}

public static class ListHelper
{
    public static List<int> CreateList(int num)
    {
        List<int> numList = new List<int>();
        numList.Add(num);
        return numList;
    }
}

“CA”中的第二个构造函数使用构造函数链接。在“this”调用中,我想将一个int转换为一个包含一个成员的List。代码通过辅助函数“CreateList”工作,但我想知道是否有比这更简洁的方法。即没有辅助方法,有没有办法做到这一点。

到目前为止,在这种情况下,我可能不会费心使用构造函数链接。想法?

4 个答案:

答案 0 :(得分:6)

尝试:

public CA(string s, int num) : this(s, new List<int>(new int[] { num }))
{
}

这应该匹配构造函数重载,该重载采用IEnumerable<T>T[]数组可转换为)。

答案 1 :(得分:3)

我会放弃ListHelper,转而支持以下内容:

public CA(string s, int num) : this(s, new List<int>(){num}){}

答案 2 :(得分:0)

我的扩展程序中有一些东西,当我没有可枚举的东西来启动列表时,应该这样做。

namespace Linq1
{
    class Program
    {
        static void Main(string[] args)
        {
            int value = 10;
            List<int> list = value.ToList();
        }
    }

    public static class Extensions
    {
        public static List<T> ToList<T>(this T lonely) where T : struct
        {
            return new List<T>(new T[] { lonely });
        }
    }
}

并在您的代码中使用:

public class CA
{
    public CA(string s, List<int> numList)
    {
        // do some initialization
    }

    public CA(string s, int num) : this(s, num.ToList())
    {
    }
}

答案 3 :(得分:0)

查看你的代码,我假设你想使用第一个CA构造函数来进行初始化,而第二个CA构造函数(string,int)不需要自己初始化 - 它只是将控制传递给第一个

首先,构造函数链的经验法则是实现链接的主要目的 - 消除重复或过于复杂的初始化代码(即链中的最低级别是包含任何实际初始化代码的唯一构造函数)。你的例子已经这样做了,这很好。

其次,如果您使用的是.NET 4,则可以在构造函数上使用可选参数来删除不必要的额外构造函数,从而消除了链接的需要。所以你可以用这种方式实现CA:

    public class CA
    {
        public CA(string s, List<int> numList = null, int num = 0)
        {
            // do some initialization
            if (numList == null)
            {
                numList = new List<int>();
                numList.Add(num);
            }
        }
    }

现在你只有一个构造函数,所以链接是不必要的。你的辅助函数和静态类也是不必要的。使用上述定义的客户端代码类似于:

        int iMyInt = 1;
        List<int> myIntList = new List<int>();
        myIntList.Add(iMyInt);
        CA caListMethod = new CA("ListMethod", myIntList);
        CA caIntMethod = new CA("IntMethod", null, iMyInt);

如果由于某种原因你不喜欢上面的'caIntMethod'调用,你可以使用.NET 4的另一个新功能,动态类型,它可以使客户端代码更清晰。您的CA类可能看起来像这样:

    public class CA
    {
        public CA(string s, dynamic InitValue)
        {
            List<int> InitList = null;
            if (InitValue is List<int>)
                InitList = InitValue;
            else if (InitValue is int)
            {
                InitList = new List<int>();
                InitList.Add(InitValue);
            }

            // Now, InitList contains your list for further initialization,
            //  if the client passed either a List<int> or an int:
            if (InitList != null)
            {
                // do some initialization
            }
        }
    }

新客户端代码看起来像这样:

        int iMyInt = 1;
        List<int> myIntList = new List<int>();
        myIntList.Add(iMyInt);
        CA caListMethod = new CA("ListMethod", myIntList);
        CA caIntMethod = new CA("IntMethod", iMyInt);

您会注意到此客户端代码与前一个示例的唯一区别在于,现在您只有一个构造函数接受两个参数,而第二个参数具有动态类型。因此,您可以在将来增强构造函数以处理许多其他类型的init值,而不会对客户端产生任何影响。

我的第二个例子的警告是动态类型在运行时自动执行类型强制,这是一些处理开销。但是,如果你想使用某种“泛型”构造函数来允许泛型引用的多态性(因此,我提到的可扩展性),那么无论如何你将在自己的代码中进行类型检查和强制。动态的美妙之处在于,.NET 4运行时代替在您自己的代码中处理这些内容,而是为您完成。所以在性能方面,它通常是一种洗涤。

如果你真的需要一个通用的,可扩展的类型,那么使用动态类型可以为客户端和类提供更清晰的代码。

希望这有帮助,

标记