Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用声明性方式而不是LINQ来提高性能?_C#_Linq - Fatal编程技术网

C# 如何使用声明性方式而不是LINQ来提高性能?

C# 如何使用声明性方式而不是LINQ来提高性能?,c#,linq,C#,Linq,让我们看看LINQ to对象。该代码引入了多少低效率 public object GetObjectToSerialize(object value, Type targetType) { var type = value.GetType(); PropertyInfo[] setToNullProperties; if (!_typeToPropertyMap.TryGetValue(type, out setToNullProperties)) {

让我们看看LINQ to对象。该代码引入了多少低效率

public object GetObjectToSerialize(object value, Type targetType)
{
    var type = value.GetType();
    PropertyInfo[] setToNullProperties;

    if (!_typeToPropertyMap.TryGetValue(type, out setToNullProperties))
    {
         var allPropeties = type.GetProperties();
         var passwordProperties = allPropeties
                                  .Where(p => p.PropertyType == typeof(string))
                                  .Where(p => p.Name.Contains("Password")).ToArray();

         var passwordWithoutEncryptedAttribute = passwordProperties
             .Where(p => !p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());

          if (passwordWithoutEncryptedAttribute.Any())
          {
              throw new InvalidOperationException();
          }

          var propertiesWithEncryptedAttribute = allPropeties.Where(p => p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());
          setToNullProperties = passwordProperties.Union(propertiesWithEncryptedAttribute).ToArray();

          _typeToPropertyMap[type] = setToNullProperties;
     }

     foreach (var property in setToNullProperties)
     {
           property.SetValue(value, null, null);
     }

     return value;
}
我想知道有多少个
.Where
.toArray
.Union

例如,
ToArray
方法不知道输出的大小,因此必须进行多次分配。如果我们有
int
s数组,而不是
PropertyInfo
,它将从4个元素开始,然后根据需要继续加倍和复制元素。我们最终可能会有过多的存储空间。例如,如果我们最终使用
33000
元素,我们将浪费大约
128KB
的动态存储(
32000 X 4字节整数

另外,当我找到
passwordProperties
时,有两个委托对象分配,两个用于调用
Enumerable.Where
。这些委托指向两个可能不同的闭包对象,每个对象都捕获了封闭变量。这些闭包对象是新类的实例,它们在二进制文件和运行时都占用了非平凡的空间。(当然,参数现在存储在两个地方,必须复制到闭包对象,然后每次访问它们时都必须进行额外的间接操作。)很可能,
Where
操作符将分配新的
IEnumerable
对象


如何使用声明式方式改进代码(因为随着编译器和运行时享受新的优化,它会变得更快)?

if中的代码对每种类型执行一次。我看不出有什么问题。即使它比必要的速度慢2倍,它仍然足够快,并且很少执行(免责声明:我编写了该代码:-)

但是你问如何加速代码。。。您可以删除几乎所有LINQ:

public object GetObjectToSerialize(object value, Type targetType) 
{
    var type = value.GetType();
    PropertyInfo[] setToNullProperties;

    if (!_typeToPropertyMap.TryGetValue(type, out setToNullProperties)) 
    {
        PropertyInfo[] allProperties = type.GetProperties();

        var setToNullProperties2 = new List<PropertyInfo>(allProperties);

        foreach (PropertyInfo property in allProperties) 
        {
            bool isEncrypted = property.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any();
            bool isPasswordProperty = false;

            if (!isEncrypted) 
            {
                isPasswordProperty = property.PropertyType == typeof(string) && property.Name.Contains("Password");

                if (isPasswordProperty) {
                    throw new InvalidOperationException();
                }
            }

            if (isEncrypted || isPasswordProperty) {
                setToNullProperties2.Add(property);
            }
        }

        _typeToPropertyMap[type] = setToNullProperties = setToNullProperties2.ToArray();
    }

    foreach (var property in setToNullProperties) 
    {
        property.SetValue(value, null, null);
    }

    return value;
}
公共对象GetObjectToSerialize(对象值,类型targetType) { var type=value.GetType(); PropertyInfo[]setToNullProperties; if(!\u typeToPropertyMap.TryGetValue(type,out setToNullProperties)) { PropertyInfo[]allProperties=type.GetProperties(); var setToNullProperties2=新列表(所有属性); foreach(所有属性中的PropertyInfo属性) { bool isEncrypted=property.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute),false); bool isPasswordProperty=false; 如果(!已加密) { isPasswordProperty=property.PropertyType==typeof(字符串)和&property.Name.Contains(“密码”); if(isPasswordProperty){ 抛出新的InvalidOperationException(); } } 如果(isEncrypted | | isPasswordProperty){ setTonullProperties 2.添加(属性); } } _TypeTopPropertyMap[type]=setToNullProperties=setToNullProperties 2.ToArray(); } foreach(setToNullProperties中的var属性) { SetValue(value,null,null); } 返回值; }
真正的加速将是在
表达式
树生成器中转换代码,因此您将删除重复反射(设置值部分)。问题是生成
表达式
树并编译它相当慢,因此,除非您在同一
类型
上使用
GetObjectToSerialize
数百次,否则不会有加速。

如果我们最终得到33000个元素
如果您在名称中包含“Password”的类型字符串的33.000个属性上运行此操作,您的问题不是Linq。
if
中的代码对每种类型执行一次。我看不出有什么问题。即使它比必要的速度慢2倍,它仍然足够快,而且很少执行(免责声明:我写的代码:-),为什么需要反射?也许找到原因可以帮助你加快速度。我完全同意@xanatos。我还想提到的是,所使用的LINQ构造都没有引入闭包。