我有一个泛型方法,我想传递一个变量,如果该变量是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循环中放了什么?
你应该只使用重载,它更简单(如果我正确理解你的问题)。
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();
在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)
{
......
}