Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.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# 检测不可变的性能方法?_C#_Multithreading_Immutability_Deep Copy - Fatal编程技术网

C# 检测不可变的性能方法?

C# 检测不可变的性能方法?,c#,multithreading,immutability,deep-copy,C#,Multithreading,Immutability,Deep Copy,我有一个实用程序,设计用于在系统中传递对象。由于它是一个多线程环境,因此该实用程序会对它传递的每个对象进行深度复制,以防止出现任何线程安全问题。我正在将我们的系统转换为使用不可变对象,以消除对该副本的需要。我想知道检测对象不可变的最佳(最快)方法是什么 我的第一个想法是只提取我们放在所有不可变对象上的属性(MessageAttribute)。正如您从下面的性能配置文件中看到的,它需要相当多的时间(大约是我所有其他检查执行时间的10倍) 否则我如何检测通过的不可变项?我可以做一个typeof()

我有一个实用程序,设计用于在系统中传递对象。由于它是一个多线程环境,因此该实用程序会对它传递的每个对象进行深度复制,以防止出现任何线程安全问题。我正在将我们的系统转换为使用不可变对象,以消除对该副本的需要。我想知道检测对象不可变的最佳(最快)方法是什么

我的第一个想法是只提取我们放在所有不可变对象上的属性(MessageAttribute)。正如您从下面的性能配置文件中看到的,它需要相当多的时间(大约是我所有其他检查执行时间的10倍)

否则我如何检测通过的不可变项?我可以做一个
typeof()
比较,这看起来性能更好,但这看起来相当笨拙,而且随着我们不断添加更多的不可变项,维护起来会非常困难

EDIT:我忘了提到布尔值被重构为变量以进行分析,实际上,存储在
isDefined
中的表达式实际上在
else if
语句中,因此会比此分析中显示的少10倍(我更关心的是平均执行时间,而不是绝对执行时间)。

制作一个接口(例如,
IImmutable
)并在所有不可变类上使用它

您只需使用
typeof()
检查此接口即可检测不可变


typeof()
是一个编译时检查,因此没有性能影响。

您使用的
只定义在
else
分支中,该分支的影响比
then
分支小10倍。只在需要时计算该值。这将使其成本降低10倍


除此之外,您还可以为计算引入缓存。您可能检查过的类型很少,因此缓存会很小。

我只缓存结果,因为类型的属性不会改变

public class SomeHelperClass
{
    private static readonly ConcurrentDictionary<Type, bool> messageAttributesCache = new ConcurrentDictionary<Type, bool>();
    private static readonly Type messageAttributeType = typeof(MessageAttribute);

    public static bool IsMessageAttributeDefined(Type type)
    {
        bool isDefined = false;
        if (messageAttributesCache.TryGetValue(type, out isDefined))
        {
            return isDefined;
        }
        isDefined = type.IsDefined(messageAttributeType, false);
        return messageAttributesCache[type] = isDefined;
    }
}

您可以将解决方案设置为通用的,我只是想知道这是一些快速的丑陋代码。尽管如此,这将有更好的性能。

我最终实现了一个哈希集,该哈希集在静态构造函数中初始化,并获取我想要传递的所有类型

private static HashSet<Type> m_PassableTypes; // 


static SynthesisExtensions() { // 
    m_PassableTypes = new HashSet<Type>();
    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
        foreach (Type type in assembly.GetTypes()) {
            if (type.IsValueType || type == typeof (string) || type.Module.Name == "FSharp.Core.dll" ||
                type.IsDefined(typeof (MessageAttribute), false)) {
                m_PassableTypes.Add(type);
            }
        }
    }
}

感谢所有的帮助!我欢迎任何关于这个解决方案的想法

我认为任何一个好的编译器都可以优化它(事实上,因为编译器应该知道System.Type是不可变的,它的方法没有副作用)…我很想在发行版中对其进行分析!感谢您的回答,我编辑了我的问题以澄清我确实这样做了,我只是对其进行了重构以使分析更容易。
private static HashSet<Type> m_PassableTypes; // 


static SynthesisExtensions() { // 
    m_PassableTypes = new HashSet<Type>();
    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
        foreach (Type type in assembly.GetTypes()) {
            if (type.IsValueType || type == typeof (string) || type.Module.Name == "FSharp.Core.dll" ||
                type.IsDefined(typeof (MessageAttribute), false)) {
                m_PassableTypes.Add(type);
            }
        }
    }
}
    Type type = instance.GetType();

    if (m_PassableTypes.Contains(type)) {
        // cache the self-reference
        referenceCache.Add(instance, instance);
        // return the value itself
        return instance;
    }