通用IEnumerable中的设置值

时间:2019-04-27 19:09:46

标签: c# generics ienumerable

我有一个通用方法,要将变量传递给该方法,如果该变量是IEnumerable,则将其所有元素设置为其默认值。这是我到目前为止的内容:

public static T set_to_default<T>(T the_obj)
{
    var the_enumerable = the_obj as IEnumerable;
    if (the_enumerable != null)
    {
        foreach (var element in the_enumerable)
        {
            // I don't know what to put here
            // I want to set each element to its default value: default(T)
        }
        return the_obj;
    }
    else
    {
        return default(T);
    }
}

我应该在 foreach 循环中放入什么?

2 个答案:

答案 0 :(得分:3)

您应该只处理重载,它要简单得多(如果我正确理解了您的问题)。

public static T SetToDefault<T>(T the_obj)
{
    return default(T);
}

public static IEnumerable<T> SetToDefault<T>(IEnumerable<T> the_enumerable)
{
    return the_enumerable.Select(value => default(T));
}

仅供参考,我使用以下功能测试了代码:

public static void Test()
{
    int myInt = 7;
    IEnumerable<int> myEnumberable = new List<int>() { 1, 4, 8, 9 };

    myInt = SetToDefault(myInt);
    myEnumberable = SetToDefault(myEnumberable);

    Console.WriteLine($"MyInt: {myInt}");
    Console.WriteLine($"MyEnumberable: {String.Join(", ", myEnumberable)}");
}

要补充一点,请记住,名称SetToDefault不是一个好选择。传递int时,您将返回int。您仍然需要自己设置值(myInt = SetToDefault(myInt);),该值与函数名称所隐含的含义有点矛盾。

请注意,第一个函数(T SetToDefault<T>(T the_obj))的参数从未使用过。要变通解决此问题(公平地说,很小),您可以使用扩展方法:

public static class Extensions {
    public static T GetDefault<T>(this T value) {
        return default(T);
    }
}

请注意,即使在此处,也必须将值设置为函数的返回值。对于void之类的原始类型,返回value = default(T);并简单地执行int 将不起作用。这就是为什么我这次将其命名为GetDefault而不是SetToDefault的原因。

var myWhatever = 3.4;
myWhatever = myWhatever.GetDefault();

答案 1 :(得分:0)

在for循环中放入以下语句:

var default_val = Activator.CreateInstance(element.GetType());

这是您设置为默认值的方式

这是您程序的完整示例

class Program
{
    static void Main(string[] args)
    {
        var my_list = new List<int>() { 1, 2, 3 };
        var list2 = set_to_default<List<int>>(my_list);
        foreach (var elem in list2)
        {
            Console.WriteLine(elem);
        }

        Console.ReadKey();
    }

    public static T set_to_default<T>(T the_obj)
    {
        IEnumerable the_enumerable = the_obj as IEnumerable;
        if (the_enumerable != null)
        {
            Type type = the_enumerable.GetType().GetGenericArguments()[0];
            Type listType = typeof(List<>).MakeGenericType(new[] { type });
            IList list = (IList)Activator.CreateInstance(listType);

            var looper = the_enumerable.GetEnumerator();

            while (looper.MoveNext())
            {
                var current_obj = looper.Current;
                current_obj = Activator.CreateInstance(current_obj.GetType());
                list.Add(current_obj);


            }

            return (T)list;
        }
        else
        {
            return default(T);
        }
    }
}

我建议使用列表而不是枚举,因为最后一个是不可变的。一旦创建它们,便无法对其进行编辑。

最后一件事情。...如果您想支持其他类型的IEnumerable而不是IList,则可以使用C#'is'关键字来解决。在这种情况下,您需要在运行时知道可枚举的基础类型。您可以使用C#'is'关键字

            if (the_enumerable is IList)
            {
                editableType = typeof(List<>).MakeGenericType(new[] { type });
            }
            else if(the_enumerable is ICollection)
            {
                ......
            }