C#使用元组Tuple绑定ListBox,以及将三元组隐式转换为坐标类型

一、新建Winform窗体应用程序TupleDemo。
在默认的Form1窗体上增加Listbox,lstPrompt,并设置属性:DrawMode为OwnerDrawFixed,添加事件DrawItem绘制项事件
然后添加两个测试按钮,如下:
二、在Form1.cs中编写如下代码【忽略设计器自动生成的代码】,源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TupleDemo
{
    public partial class Form1 : Form
    {
        /*
         * 元组最大的用处就是,不用为了 一些简单的结构或对象而去新建一个类了。
注意的是tuple最多支持8个成员,如果成员超过了8个我们可以将第8个成员当成一个元组,通过元祖的嵌套去完成。
超过8个成员最好直接使用类 或 结构
        */
        public Form1()
        {
            InitializeComponent();

            // 定义一个元组集合,每个元组的第一个是显示信息,第二个是代表是否是正常
            //lstPrompt.DataSource = TupleArray;//这里不能使用Datasource
            lstPrompt.DisplayMember = "Item1";
            lstPrompt.ValueMember = "Item2";
        }

        private void lstPrompt_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0)
                return;
            Tuple<string, bool> tuple = ((ListBox)sender).Items[e.Index] as Tuple<string, bool>;
            Color vColor = e.ForeColor;
            if (!tuple.Item2)
            {
                //有异常或错误显示红色
                vColor = Color.Red;
            }
            else
            {
                vColor = Color.FromKnownColor(KnownColor.LightSkyBlue);
            }
            e.Graphics.FillRectangle(new SolidBrush(vColor), e.Bounds);
            e.Graphics.DrawString(tuple.Item1, e.Font,
                new SolidBrush(e.ForeColor), e.Bounds);
            e.DrawFocusRectangle();
        }

        private void btnAddItems_Click(object sender, EventArgs e)
        {
            lstPrompt.Items.Clear();
            AddElement("加载MES相关基本配置成功。", true, lstPrompt);
            AddElement("加载MES日志【保存目录与天数】配置出错,原因:未配置指定的节点X", false, lstPrompt);
            AddElement("加载【侧缝焊电芯校验基本配置】成功", true, lstPrompt);
            AddElement("加载MES日志【保存目录与天数】配置成功", true, lstPrompt);
            AddElement(string.Format("正在加载扫码枪配置,以及开启扫码枪相应串口..."), true, lstPrompt);
            AddElement("打开串口COM1失败,原因:COM1不存在", false, lstPrompt);
            AddElement("打开【EIP】软件成功", true, lstPrompt);
        }

        /// <summary>
        /// 为ListBox增加一行元素
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="isNormal"></param>
        /// <param name="listBox"></param>
        static void AddElement(string msg, bool isNormal, ListBox listBox)
        {
            Thread.Sleep(500);
            //int curIndex = 
            listBox.Items.Add(new Tuple<string, bool>(msg, isNormal));
            //listBox.SelectedIndex = curIndex;
            listBox.TopIndex = listBox.Items.Count - listBox.Height / listBox.ItemHeight;
            Application.DoEvents();
        }

        private void btnCoord_Click(object sender, EventArgs e)
        {
            //可以使用静态类,来创建Tuple
            Tuple<double, double, double> Coord = Tuple.Create(1.11, 22.22, 333.33);
            AddElement("下面开始【测试三元组  隐式转化为XYZ坐标】", false, lstPrompt);
            AddElement($"各个项的值:(X:{Coord.Item1},Y:{Coord.Item2},Z:{Coord.Item3})", true, lstPrompt);
            //这行代码是个隐式转换
            Coordinate crd = Coord;
            AddElement($"【将三元组隐式转换为坐标类型】,结果:({crd.X},{crd.Y},{crd.Z})", true, lstPrompt);
        }
    }
    
}

三、新建类Coordinate,Coordinate.cs源代码如下,测试隐式转换操作符。源代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TupleDemo
{
    /// <summary>
    /// 表示空间坐标的类
    /// </summary>
    public class Coordinate
    {
        /// <summary>
        /// X方向的坐标【多为左右方向】
        /// </summary>
        public double X { get; set; }
        /// <summary>
        /// Y方向的坐标【多为前后方向】
        /// </summary>
        public double Y { get; set; }
        /// <summary>
        /// Z方向的坐标【多为上下方向】
        /// </summary>
        public double Z { get; set; }

        /// <summary>
        /// 隐式转换:将三元组隐式转换为坐标类型
        /// </summary>
        /// <param name="coord"></param>
        public static implicit operator Coordinate(Tuple<double, double, double> coord)
        {
            return new Coordinate() { X = coord.Item1, Y = coord.Item2, Z = coord.Item3 };
        }

        /// <summary>
        /// 操作符重载 重载 等于操作符 必须 重载 不等于操作符
        /// 重载 等于操作符,最好也重载 Equals(object obj) 和 GetHashCode()函数
        /// </summary>
        /// <param name="crd1"></param>
        /// <param name="crd2"></param>
        /// <returns></returns>
        public static bool operator ==(Coordinate crd1, Coordinate crd2)
        {
            return crd1.X == crd2.X && crd1.Y == crd2.Y && crd1.Z == crd2.Z;
        }

        public static bool operator !=(Coordinate crd1, Coordinate crd2)
        {
            return !(crd1.X == crd2.X && crd1.Y == crd2.Y && crd1.Z == crd2.Z);
        }

        public override bool Equals(object obj)
        {
            var coordinate = obj as Coordinate;
            return coordinate != null &&
                   X == coordinate.X &&
                   Y == coordinate.Y &&
                   Z == coordinate.Z;
        }

        public override int GetHashCode()
        {
            var hashCode = -307843816;
            hashCode = hashCode * -1521134295 + X.GetHashCode();
            hashCode = hashCode * -1521134295 + Y.GetHashCode();
            hashCode = hashCode * -1521134295 + Z.GetHashCode();
            return hashCode;
        }
    }
}
四、运行测试结果截图:

五、附录:
关于元组的源码请查看微软参考文档:
https://referencesource.microsoft.com/#mscorlib/system/tuple.cs,1806cf6634f5a371
源码如下:元组就是一个类,有关键属性Item1,Item2,...ItemN代表第一项、第二项、第N项
[Serializable]
    public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple {
 
        private readonly T1 m_Item1;
        private readonly T2 m_Item2;
 
        public T1 Item1 { get { return m_Item1; } }
        public T2 Item2 { get { return m_Item2; } }
 
        public Tuple(T1 item1, T2 item2) {
            m_Item1 = item1;
            m_Item2 = item2;
        }
 
        public override Boolean Equals(Object obj) {
            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
        }
 
        Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
            if (other == null) return false;
 
            Tuple<T1, T2> objTuple = other as Tuple<T1, T2>;
 
            if (objTuple == null) {
                return false;
            }
 
            return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2);
        }
 
        Int32 IComparable.CompareTo(Object obj) {
            return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
        }
 
        Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
            if (other == null) return 1;
 
            Tuple<T1, T2> objTuple = other as Tuple<T1, T2>;
 
            if (objTuple == null) {
                throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
            }
 
            int c = 0;
 
            c = comparer.Compare(m_Item1, objTuple.m_Item1);
 
            if (c != 0) return c;
 
            return comparer.Compare(m_Item2, objTuple.m_Item2);
        }
 
        public override int GetHashCode() {
            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
        }
 
        Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
            return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2));
        }
 
        Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer) {
            return ((IStructuralEquatable) this).GetHashCode(comparer);
        }
        public override string ToString() {
            StringBuilder sb = new StringBuilder();
            sb.Append("(");
            return ((ITupleInternal)this).ToString(sb);
        }
 
        string ITupleInternal.ToString(StringBuilder sb) {
            sb.Append(m_Item1);
            sb.Append(", ");
            sb.Append(m_Item2);
            sb.Append(")");
            return sb.ToString();
        }
 
        /// <summary>
        /// The number of positions in this data structure.
        /// </summary>
        int ITuple.Length => 2;
 
        /// <summary>
        /// Get the element at position <param name="index"/>.
        /// </summary>
        object ITuple.this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return Item1;
                    case 1:
                        return Item2;
                    default:
                        throw new IndexOutOfRangeException();
                }
            }
        }
    }
参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值