Comparing structs for equality without boxing

北战南征 提交于 2019-12-19 17:34:34

问题


I came across an extension method that applies to structs (SomeStruct) and returns whether or not the value is equal to the default(SomeStruct) (when the parameterless constructor is called).

public static bool IsDefault<T> (this T value)
    where T : struct
{
    return (!EqualityComparer<T>.Default.Equals(value, default(T)));
}

This got me wondering whether the struct was being boxed. This is purely out of curiosity as there are pros/cons to boxing/passing by value depending on the context.

Assumptions:

  1. The first of the following methods is illegal since structs do not implicitly override the equality operators ==/!=.
  2. The second "appears" to avoid boxing.
  3. The third method should always box the struct since it's calling object.Equals(object o).
  4. The fourth has both overloads available (object/T) so I'm assuming it will avoid boxing as well. However, the target struct would need to implement the IEquatable<T> interface, making the helper extension method not very helpful.

Variations:

public static bool IsDefault<T> (this T value)
    where T : struct
{
    // Illegal since there is no way to know whether T implements the ==/!= operators.
    return (value == default(T));
}

public static bool IsDefault<T> (this T value)
    where T : struct
{
    return (!EqualityComparer<T>.Default.Equals(value, default(T)));
}

public static bool IsDefault<T> (this T value)
    where T : struct
{
    return (value.Equals(default(T)));
}

public static bool IsDefault<T> (this T value)
    where T : struct, IEquatable<T>
{
    return (value.Equals(default(T)));
}

This question is about confirming the above assumptions and if I am misunderstanding and/or leaving something out.


回答1:


  1. The first of the following methods is illegal since structs do not implicitly override the equality operators ==/!=.

True.

  1. The second "appears" to avoid boxing.

The signature of the called method is EqualityComparer<T>.Equals(T,T) which uses the type T for the parameters, so it does not require boxing to call.

The implementation of the default comparer checks if T is IEquatable<T> and if so uses a comparer that uses IEquatable<T>.Equals and else uses a comparer for Object.Equals, so internally there might be boxing applied if the struct is not IEquatable ('only if needed').

  1. The third method should always box the struct since it's calling object.Equals(object o).

True.

  1. The fourth has both overloads available (object/T) so I'm assuming it will avoid boxing as well. However, the target struct would need to implement the IEquatable interface, making the helper extension method not very helpful.

Yes, it does not require boxing, as per this SO answer. This is the effective code you get for the specific case of T : IEquatable from the EqualityComparer<T>.Default.



来源:https://stackoverflow.com/questions/36822246/comparing-structs-for-equality-without-boxing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!