一、新建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(); } } } }
C#使用元组Tuple绑定ListBox,以及将三元组隐式转换为坐标类型
最新推荐文章于 2023-11-25 11:27:37 发布