首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用收缩法、toArray法和fromArray法改进toArray

如何用收缩法、toArray法和fromArray法改进toArray
EN

Stack Overflow用户
提问于 2015-09-20 16:31:41
回答 3查看 139关注 0票数 2

我需要在System.Tuple中实现一个处理.Net类的方法。做这件事最好的方法是什么?扩展方法,子类完整的元组类,还是创建一个基于System.Tuple源代码的新类?

该方法输入一个Tuple<T1,T2..Tn>,并根据掩码(int或boolean)返回一个Tuple<T1..Tm> (m<n)。如何替换开关-大小写语句和反射的使用?我怎样才能提高性能?

代码语言:javascript
复制
public static object shrink(this object source, params int[] mask)
{
    PropertyInfo[] prop = source.GetType().GetRuntimeProperties().ToArray<PropertyInfo>();
    object[] tmp = new object[mask.Length];
    int index = 0;
    for (int i = 0; i < mask.Length; i++)
    {
        if (mask[i] != 0)
        {
            tmp[index] = prop[i].GetValue(source, null);
            index++;
        }
    }
    switch (index)
    {
        case 1: return Tuple.Create(tmp[0]);
        case 2: return Tuple.Create(tmp[0], tmp[1]);
            ....
            ....
    }
}

以同样的方式,我需要实现一个Tuple到数组,一个数组到Tuple方法。

代码语言:javascript
复制
2) public static object toArray(this object source)

输入:Tuple<T1..Tn>输出:object[]

代码语言:javascript
复制
3) public static object FromArray(this object source)

输入:object[]输出Tuple<T1..Tn)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-20 17:47:38

这很可能不会改善函数的运行时,但它将避免切换情况。

代码语言:javascript
复制
private object StripTuple(object tuple, int[] mask)
{
    int[] indexes = mask.Select((v, i) => new { val = v, index = i }).Where(o => o.val == 1).Select(i => i.index).ToArray();
    object[] items = new object[indexes.Length];
    Type[] tupleTypes = new Type[indexes.Length];
    var originalTupleType = tuple.GetType();
    var genericArgs = originalTupleType.GetGenericArguments();

    for (var i = 0; i < indexes.Length; i++)
    {
        items[i] = originalTupleType.GetProperty("Item" + (indexes[i] + 1)).GetValue(tuple);
        tupleTypes[i] = genericArgs[indexes[i]];
    }

    Type tupleType = Type.GetType("System.Tuple`" + indexes.Length);
    Type newTupleType = tupleType.MakeGenericType(tupleTypes);
    return Activator.CreateInstance(newTupleType, items);
}

用法:

代码语言:javascript
复制
var t1 = new Tuple<int, int, int, string, double, string, int>(1, 2, 3, "4", 5.7, "6", 7);
var newTuple = StripTuple(t1, new int[7]{0,0,0,1,1,0,1}); // "4",5.7,7

函数将获得第一个m参数(m <=元组的长度)。

如果输入为Tuple<int,int,string,int>,长度=3,则输出类型为Tuple<int,int,string>

票数 0
EN

Stack Overflow用户

发布于 2015-09-20 17:18:56

为了避免反射,您唯一的选择是为所有元组创建重载。泛型元组类型:

代码语言:javascript
复制
public static object shrink<T1>(this Tuple<T1> tuple, params int[] mask) {
}

public static object shrink<T1, T2>(this Tuple<T1, T2> tuple, params int[] mask) {
}

...

ToArray()方法也是如此。尽管如此,FromArray和收缩的返回类型仍然是"object“,因为您返回不同的元组,并且它们不共享任何可用的公共类或接口。你为什么要这么做?我有种感觉,你可能不需要在你的任务中使用元组类。

票数 0
EN

Stack Overflow用户

发布于 2015-09-20 21:08:14

1)这与埃米尔的回答相同,只是更多的是LINQ。

代码语言:javascript
复制
public static object shrink(this object source, params int[] mask)
{
    var props = source.GetType().GetProperties();
    var values = mask
                .Select((val, index) => new { val, index })
                .Where(x => x.val != 0)
                .Select(x => props[x.index])
                .Select(prop => new { prop, value = prop.GetValue(source) })
                .ToList();

    var type = Type.GetType("System.Tuple`" + values.Count)
              .MakeGenericType(values.Select(x => x.prop.PropertyType).ToArray());
    var arguments = values.Select(x => x.value).ToArray();
    return Activator.CreateInstance(type, arguments);
}

2)如果适合,可以返回动态类型,动态决定定义。类似于:

代码语言:javascript
复制
public static object shrink(this object source, params int[] mask)
{
    var props = source.GetType().GetProperties();
    var items = mask
               .Select((val, index) => new { val, index })
               .Where(x => x.val != 0)
               .Select((x, index) => new
               {
                   name = "Item" + index,
                   val = props[x.index].GetValue(source)
               })
               .ToList();

    var expando = new ExpandoObject() as IDictionary<string, object>;
    foreach (var item in items)
        expando[item.name] = item.val;

    return expando;
}

3)最后,您应该能够使用表达式树和使用预编译的委托来生成运行时元组,而不是反射,但是由于这整个过程不是泛型的,所以您必须使用DynamicInvoke,这会更慢,所以我不确定性能的提高。DynamicInvoke非常慢,是框架中最慢的构造之一。如果性能很重要,您可以编写单独的重载,如Evk所示。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32681711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档