可以相互比较的自定义类型集

发布于 2024-12-12 07:14:58 字数 490 浏览 0 评论 0原文

我想构建一组在代表不同类型值的接口之上构建的对象:

integers
strings
datetime

这些对象将能够执行以下操作:

IData intValue = new IntData();
IData intValue2 = new IntData();

bool result = intValue.EqualsTo(intValue2);

IData dateTimeData = new DateTimeData();
IData dateTimeData2 = new DateTimeData();

bool result = dateTimeData.GreaterThan(dateTimeData2);

所以我需要一个接口,但是如何设置比较等的能力? 如果类型是 IEnumerable 呢?

public interface IData
{

}

I want to build a set of objects built on top of an interface that represent different types of values:

integers
strings
datetime

And these objects will be able to perform operations like:

IData intValue = new IntData();
IData intValue2 = new IntData();

bool result = intValue.EqualsTo(intValue2);

IData dateTimeData = new DateTimeData();
IData dateTimeData2 = new DateTimeData();

bool result = dateTimeData.GreaterThan(dateTimeData2);

So I need an interface, but how do I setup the ability to compare etc?
What about if the type is a IEnumerable?

public interface IData
{

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

々眼睛长脚气 2024-12-19 07:14:58

我认为您基本上是在寻找变体类型的 C# 版本。我现在能想到的最接近的东西是 C# 动态:

  public class DynamicComparer : IComparer<dynamic>
  { // ...

不幸的是,这是非法的,因此您可以诉诸

  public class DynamicComparer : IComparer<object>
  {

并实现其中您想要的逻辑。

Brainwave:

我刚刚想到的另一种方法是提供一个具有隐式转换的统一类 - 是的我不推荐这样做 - 但我确实喜欢想出最有创意的方式来回答原始问题< /em>:

public class MyData : IData, IComparable<MyData>
{
    public static implicit operator MyData(string s)    { /* ... */ }
    public static implicit operator MyData(DateTime dt) { /* ... */ }
    public static implicit operator MyData(int dt)      { /* ... */ }

    // implement IComparable<MyData> members...

    // e.g.:
    private dynamic variant_data; // or, the desired default representation
                                  // for comparisons, e.g. string?
}

更新 这是一个半完整的示例,说明如何滥用隐式转换来实现您想要的目标(几乎透明地比较析取类型):https://ideone.com/WwI87

using System;
using System.Collections.Generic;

public class Program
{
    public class MyData : IEquatable<MyData>, IComparable<MyData>
    {
        public static implicit operator MyData(string s)    { var data = new MyData(); /* TODO */ return data; }
        public static implicit operator MyData(DateTime dt) { var data = new MyData(); /* TODO */ return data; }
        public static implicit operator MyData(int dt)      { var data = new MyData(); /* TODO */ return data; }

        // implement IComparable<MyData> members...
        // implement IEquatable<MyData> members...

        // override object.Equals()
        // override object.GetHashCode()
        public static bool operator <(MyData a, MyData b) { return Comparer<MyData>.Default.Compare(a,b) == -1; }
        public static bool operator >(MyData a, MyData b) { return Comparer<MyData>.Default.Compare(a,b) == +1; }

        // e.g.: 
        // the desired default representation for comparisons, e.g. string?
        // use 'dynamic' on C# 4.0 and beyond
        private object/*dynamic*/ variant_data;

        public int CompareTo(MyData other)
        {
            // TODO implement your own logic
            return GetHashCode().CompareTo(null != other ? other.GetHashCode() : 0);
        }

        // TODO implement your own equality logic:
        public bool Equals(MyData other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.variant_data, variant_data);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (MyData)) return false;
            return Equals((MyData) obj);
        }

        public override int GetHashCode() { return (variant_data != null ? variant_data.GetHashCode() : 0); }
        public static bool operator ==(MyData left, MyData right) { return Equals(left, right); }
        public static bool operator !=(MyData left, MyData right) { return !Equals(left, right); }
    }

    public static void Main(string[] args)
    {
        var cmp = Comparer<MyData>.Default;

        string s = "123";
        int i = 234;
        DateTime dt = DateTime.Now;

        if (-1  == cmp.Compare(s, i))  Console.WriteLine("s < i"); 
        if (+1 == cmp.Compare(dt, i)) Console.WriteLine("dt > i");

        // or even:
        if ((MyData) s > i) Console.WriteLine("s > i");
        if ((MyData) dt< i) Console.WriteLine("dt < i");
    }
}

I think you are basically looking for a C# version of a variant type. The closest thing that I can think of right now is C# dynamics:

  public class DynamicComparer : IComparer<dynamic>
  { // ...

Unfortunately, that would be illegal, so you could resort to

  public class DynamicComparer : IComparer<object>
  {

and implement the logic you wanted inside that.

Brainwave:

Another approach that just occurred to me, is to provide a unifying class with implicit comversions - yeah I don't recommend this - but I do love to think of the most creative ways in which to answer the original question:

public class MyData : IData, IComparable<MyData>
{
    public static implicit operator MyData(string s)    { /* ... */ }
    public static implicit operator MyData(DateTime dt) { /* ... */ }
    public static implicit operator MyData(int dt)      { /* ... */ }

    // implement IComparable<MyData> members...

    // e.g.:
    private dynamic variant_data; // or, the desired default representation
                                  // for comparisons, e.g. string?
}

Update Here is a semi-fullblown example of how you could abuse implicit conversions to just about achieve what you want (almost transparent comparison of disjunct types): https://ideone.com/WwI87

using System;
using System.Collections.Generic;

public class Program
{
    public class MyData : IEquatable<MyData>, IComparable<MyData>
    {
        public static implicit operator MyData(string s)    { var data = new MyData(); /* TODO */ return data; }
        public static implicit operator MyData(DateTime dt) { var data = new MyData(); /* TODO */ return data; }
        public static implicit operator MyData(int dt)      { var data = new MyData(); /* TODO */ return data; }

        // implement IComparable<MyData> members...
        // implement IEquatable<MyData> members...

        // override object.Equals()
        // override object.GetHashCode()
        public static bool operator <(MyData a, MyData b) { return Comparer<MyData>.Default.Compare(a,b) == -1; }
        public static bool operator >(MyData a, MyData b) { return Comparer<MyData>.Default.Compare(a,b) == +1; }

        // e.g.: 
        // the desired default representation for comparisons, e.g. string?
        // use 'dynamic' on C# 4.0 and beyond
        private object/*dynamic*/ variant_data;

        public int CompareTo(MyData other)
        {
            // TODO implement your own logic
            return GetHashCode().CompareTo(null != other ? other.GetHashCode() : 0);
        }

        // TODO implement your own equality logic:
        public bool Equals(MyData other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.variant_data, variant_data);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (MyData)) return false;
            return Equals((MyData) obj);
        }

        public override int GetHashCode() { return (variant_data != null ? variant_data.GetHashCode() : 0); }
        public static bool operator ==(MyData left, MyData right) { return Equals(left, right); }
        public static bool operator !=(MyData left, MyData right) { return !Equals(left, right); }
    }

    public static void Main(string[] args)
    {
        var cmp = Comparer<MyData>.Default;

        string s = "123";
        int i = 234;
        DateTime dt = DateTime.Now;

        if (-1  == cmp.Compare(s, i))  Console.WriteLine("s < i"); 
        if (+1 == cmp.Compare(dt, i)) Console.WriteLine("dt > i");

        // or even:
        if ((MyData) s > i) Console.WriteLine("s > i");
        if ((MyData) dt< i) Console.WriteLine("dt < i");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文