【问题标题】:Is there a 1-value "class wrapper" type in .NET?.NET 中是否有 1 值“类包装器”类型?
【发布时间】:2017-04-12 20:45:01
【问题描述】:

我正在处理现有的自定义集合类型。目前无法更改约束。

class CustomDict<TKey, TValue>
where TValue : class

我想使用结构类型(即bool)作为值。

是否有一个标准 .NET/CLR 类型可以用作类环绕结构包装器,这样以下是有效的?

new CustomDict<string, Wrapper<bool>>(..)

隐式/显式转换很简洁,但不是必需的。当然,创建自定义类是微不足道的 - 问题是关于 [重新] 使用通用/核心类类型。

【问题讨论】:

  • 哦,啊啊啊啊!免费积分.. SO 作为扶手椅效果很好。
  • 问题是为什么添加了该约束。制作一个包装值类型的类非常容易,但它必须提供什么才能满足这个奇怪的要求?
  • 当然,创建一个自定义类很简单我可能会这样做。
  • 你写这个问题的时间可能比你写自己的解决方案要多 2 个数量级。
  • @user2864740 花更少的时间来获得更好的结果,而不是浪费很多其他人的时间来获得更快更好的结果是愚蠢的吗?为什么会很愚蠢?

标签: c# .net class struct wrapper


【解决方案1】:

我找到了这个Tuple 类:

https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx

您可以将Tuple&lt;bool&gt; 用于TValue 类型参数。只需调用Create 即可创建实例,例如:

Tuple.Create(true)

【讨论】:

  • 一个很好的答案,但我个人认为我宁愿花 30 秒来拼凑一个自定义类,以避免真正丑陋的 Item1 属性访问 @987654328 中的值@.
  • @MattBurland 我同意。我也确信 OP 知道创建自定义类,他可能有一些理由不这样做。
  • 谢谢,这就是我要找的东西——我在 C# 中输入了 Tuple1 并错过了 Tuple&lt;..&gt; 直到一分钟后的网络搜索(我也错误地认为元组是值类型,这就是为什么我最终开始使用 MSDN 的原因)!这是一个本地化用例,不会超出私有方法。
【解决方案2】:

正如您自己所说,这很容易做到。例如:

public class StructWrapper<T> where T : struct
{
    public T Value { get; private set; }

    public StructWrapper(T val)
    {
        Value = val;
    }

    public static implicit operator T(StructWrapper<T> w)
    {
        return w.Value;
    }

    public static implicit operator StructWrapper<T>(T s)
    {
        return new StructWrapper<T>(s);
    }
}

然后你可以这样做:

var bw = new StructWrapper<bool>(true);

由于隐式转换,您可以执行以下操作:

if (bw)
{
    Console.WriteLine("True!");
}

它应该可以工作。

如果您需要/想要实现平等,可以将其添加到StructWrapper&lt;T&gt;:

public override bool Equals(object obj)
{
    if (obj is StructWrapper<T>) 
    {
        return Value.Equals(((StructWrapper<T>)obj).Value);
    }
    return Value.Equals(obj);
}

public override int GetHashCode()
{
    return Value.GetHashCode();
}

public static bool operator ==(StructWrapper<T> a, StructWrapper<T> b)
{
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    return a.Value.Equals(b.Value);
}

public static bool operator !=(StructWrapper<T> a, StructWrapper<T> b)
{
    return !(a == b);
}

public static bool operator ==(StructWrapper<T> a, T b)
{
    return a.Value.Equals(b);
}

public static bool operator !=(StructWrapper<T> a, T b)
{
    return !(a == b);
}

public static bool operator ==(T b, StructWrapper<T> a)
{
    return a.Value.Equals(b);
}

public static bool operator !=(T b, StructWrapper<T> a)
{
    return !(a == b);
}

这会让你做这样的事情:

var isbwTrue = bw == true;

【讨论】:

  • 虽然我在这种特定情况下使用 Tuple ,但在某些情况下包装器肯定会更干净。然而,这也说明了添加一次性代码的问题:它没有正确实现 Equality(在包装的值上),这会破坏这里的用法。现有的 Tuple 类型可以。
  • 这是在一个类中包装一个结构。至于平等,如果你愿意,你当然可以实现
  • 这个问题清楚地询问如何重用现有类型,而不是如何实现一个:“当然,创建一个自定义类是微不足道的 - 问题是关于 [重新] 使用一个公共/核心类类型。”
猜你喜欢
  • 2022-01-19
  • 2011-04-07
  • 2020-07-17
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 2010-09-10
  • 1970-01-01
  • 2020-03-13
相关资源
最近更新 更多