简体   繁体   English

在C#中使用一对(三重等)值作为一个值的最佳方法是什么?

[英]What's the best way of using a pair (triple, etc) of values as one value in C#?

That is, I'd like to have a tuple of values. 也就是说,我想要一个价值元组。

The use case on my mind: 我心中的用例:

Dictionary<Pair<string, int>, object>

or 要么

Dictionary<Triple<string, int, int>, object>

Are there built-in types like Pair or Triple? 是否有内置类型,如Pair或Triple? Or what's the best way of implementing it? 或者实施它的最佳方式是什么?

Update There are some general-purpose tuples implementations described in the answers, but for tuples used as keys in dictionaries you should additionaly verify correct calculation of the hash code. 更新答案中描述了一些通用元组实现,但对于在字典中用作键的元组,您应该另外验证哈希码的正确计算。 Some more info on that in another question . 在另一个问题中有关于此的更多信息。

Update 2 I guess it is also worth reminding, that when you use some value as a key in dictionary, it should be immutable. 更新2我想还值得提醒的是,当你在字典中使用某个值作为键时,它应该是不可变的。

Builtin Classes 内置类

In certain specific cases, the .net framework already provides tuple-like classes that you may be able to leverage. 在某些特定情况下,.net框架已经提供了类似元组的类,您可以利用它们。

Pairs and Triples 对和三人组

The generic System.Collections.Generic.KeyValuePair class could be used as an adhoc pair implementation. 通用的System.Collections.Generic.KeyValuePair类可以用作adhoc对实现。 This is the class that the generic Dictionary uses internally. 这是泛型Dictionary在内部使用的类。

Alternatively, you may be able to make do with the System.Collections.DictionaryEntry structure that acts as a rudimentary pair and has the advantage of being available in mscorlib. 或者,您可以使用System.Collections.DictionaryEntry结构,该结构充当基本对,并具有在mscorlib中可用的优势。 On the down side, however, is that this structure is not strongly typed. 然而,不利的是,这种结构不是强类型的。

Pairs and Triples are also available in the form of the System.Web.UI.Pair and System.Web.UI.Triplet classes. 还可以以System.Web.UI.PairSystem.Web.UI.Triplet类的形式提供Pairs和Triple。 Even though theses classes live in the the System.Web assembly they might be perfectly suitable for winforms development. 尽管这些类存在于System.Web程序集中,但它们可能非常适合winforms开发。 However, these classes are not strongly typed either and might not be suitable in some scenarios, such as a general purposed framework or library. 但是,这些类也不是强类型的,也可能不适用于某些场景,例如通用框架或库。

Higher order tuples 更高阶的元组

For higher order tuples, short of rolling your own class, there may not be a simple solution. 对于更高阶的元组,如果没有滚动自己的类,可能没有一个简单的解决方案。

If you have installed the F# language , you could reference the FSharp.Core.dll that contains a set of generic immutable Microsoft.Fsharp.Core.Tuple classes up to generic sextuples. 如果已安装F#语言 ,则可以引用包含一组通用不可变Microsoft.Fsharp.Core.Tuple类的FSharp.Core.dll ,直到通用的六进制文件。 However, even though an unmodified FSharp.Code.dll can be redistributed, F# is a research language and a work in progress so this solution is likely to be of interest only in academic circles. 但是,即使可以重新分发未修改的FSharp.Code.dll ,F#也是一种研究语言并且正在进行中,因此这种解决方案可能只对学术界有兴趣。

If you do not want to create your own class and are uncomfortable referencing the F# library, one nifty trick could consist in extending the generic KeyValuePair class so that the Value member is itself a nested KeyValuePair. 如果您不想创建自己的类并且引用F#库感到不舒服,那么一个很好的技巧可能在于扩展通用KeyValuePair类,以便Value成员本身就是嵌套的KeyValuePair。

For instance, the following code illustrates how you could leverage the KeyValuePair in order to create a Triples: 例如,以下代码说明了如何利用KeyValuePair创建Triples:

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

This allows to extend the class to any arbitrary level as is required. 这允许根据需要将类扩展到任意级别。

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string> quadruple =
    new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>();
KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string> quintuple =
    new KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string>();

Roll Your Own 滚动你自己

In other cases, you might need to resort to rolling your own tuple class, and this is not hard. 在其他情况下,您可能需要求助于滚动自己的元组类,这并不难。

You can create simple structures like so: 您可以创建简单的结构,如下所示:

struct Pair<T, R>
{
    private T first_;
    private R second_;

    public T First
    {
        get { return first_; }
        set { first_ = value; }
    }

    public R Second
    {
        get { return second_; }
        set { second_ = value; }
    }
}

Frameworks and Libraries 框架和图书馆

This problem has been tackled before and general purpose frameworks do exist. 之前已经解决了这个问题,并且确实存在通用框架。 Below is a link to one such framework: 以下是一个这样的框架的链接:

public struct Pair<T1, T2>
{
    public T1 First;
    public T2 Second;
}

public struct Triple<T1, T2, T3>
{
    public T1 First;
    public T2 Second;
    public T3 Third;
}

Fast-forward to 2010, .NET 4.0 now supports n-tuples of arbitrary n . 快进到2010年,.NET 4.0现在支持任意n的n元组 These tuples implement structural equality and comparison as expected. 这些元组按预期实现结构上的平等和比较。

Pair and Triplet are existing classes in .net see msdn: Pair和Triplet是.net中现有的类,请参阅msdn:

Triplet 三联

Pair

I recently came across them, while playing around with viewstate decoding 我最近遇到了他们,同时玩了viewstate解码

I have implemented a tuple library in C#. 我在C#中实现了一个元组库。 Visit http://www.adventuresinsoftware.com/generics/ and click on the "tuples" link. 访问http://www.adventuresinsoftware.com/generics/并单击“元组”链接。

I usually just create my own struct, containing the values. 我通常只创建自己的结构,包含值。 It's often a bit more readable ;) 它通常更具可读性;)

KeyValuePair is the best class to extend if you don't want to create your own classes. 如果您不想创建自己的类, KeyValuePair是最好的扩展类。

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

You can extend it to as many levels as you want. 您可以将其扩展到任意数量的级别。

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string> quadruple =
   new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string>();

Note : The classes Triplet and Pair exists inside the System.Web -dll, so it's not very suitable for other solutions than ASP.NET. 三联存在的System.Web -dll中的类,所以它不是很适合ASP.NET比其他解决方案。

You can relatively easily create your own tuple classes, the only thing that potentially gets messy is your equality and hashcode overrides (essential if you're going to use them in dictionaries). 您可以相对轻松地创建自己的元组类,唯一可能变得混乱的是您的相等和哈希码覆盖(如果您要在字典中使用它们,则必不可少)。

It should be noted that .Net's own KeyValuePair<TKey,TValue> struct has relatively slow equality and hashcode methods . 应该注意的是.Net自己的KeyValuePair<TKey,TValue> struct具有相对较慢的相等和哈希码方法

Assuming that isn't a concern for you there is still the problem that the code ends up being hard to figure out: 假设这不是你的问题,那么仍然存在代码最终难以弄清楚的问题:

public Tuple<int, string, int> GetSomething() 
{
    //do stuff to get your multi-value return
}

//then call it:
var retVal = GetSomething();

//problem is what does this mean?
retVal.Item1 / retVal.Item3; 
//what are item 1 and 3?

In most of these cases I find it easier to create a specific record class (at least until C#4 makes this compiler-magic) 在大多数情况下,我发现创建一个特定的记录类更容易(至少在C#4使这个编译器变得神奇之前)

class CustomRetVal {
    int CurrentIndex { get; set; }
    string Message { get; set; }
    int CurrentTotal { get; set; }
}

var retVal = GetSomething();

//get % progress
retVal.CurrentIndex / retVal.CurrentTotal;

One simple solution has no been mentioned yet. 尚未提及一个简单的解决方案。 You can also just use a List<T> . 您也可以使用List<T> It's built in, efficient and easy to use. 它内置,高效且易于使用。 Granted, it looks a bit weird at first, but it does its job perfectly, especially for a larger count of elements. 当然,它起初看起来有点奇怪,但它完美地完成了它的工作,特别是对于更多的元素数量。

NGenerics - the popular .Net algorithms and data structures library, has recently introduced immutable data structures to the set. NGenerics--流行的.Net算法和数据结构库,最近向该集合引入了不可变数据结构。

The first immutable ones to implement were pair and tuple classes. 实现的第一个不可变的是pairtuple类。 The code is well covered with tests and is quite elegant. 代码完全覆盖了测试,非常优雅。 You can check it here . 你可以在这里查看 They are working on the other immutable alternatives at the moment and they should be ready shortly. 他们目前正在研究其他不可改变的替代方案,他们应该很快做好准备。

没有内置的ins,但是Pair <T,R>类很容易创建。

是的,有System.Web.UI.Pair和System.Web.UI.Triplet(它有一个重载的对象类型行为的创建者!)

对于第一种情况,我通常使用

Dictionary<KeyValuePair<string, int>, object>

There are not built-in classes for that. 没有内置的类。 You can use KeyValuePair or roll out your own implementation. 您可以使用KeyValuePair或推出自己的实现。

You could use System.Collections.Generic.KeyValuePair as your Pair implementation. 您可以使用System.Collections.Generic.KeyValuePair作为您的Pair实现。

Or you could just implement your own, they aren't hard: 或者你可以实现自己的,他们并不难:

public class Triple<T, U, V>
{
  public T First {get;set;}
  public U Second {get;set;}
  public V Third {get;set;}
}

Of course, you may someday run into a problem that Triple(string, int, int) is not compatible with Triple(int, int, string). 当然,有一天你可能会遇到Triple(string,int,int)与Triple(int,int,string)不兼容的问题。 Maybe go with System.Xml.Linq.XElement instead. 也许改为使用System.Xml.Linq.XElement。

There are also the Tuple<> types in F#; F#中还有Tuple <>类型; you just need to reference FSharp.Core.dll. 你只需要参考FSharp.Core.dll。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将键/值对绑定到asp标签的最佳方法是什么 - What's the best way to bind key/value pair to an asp label 在C#中管理键值对的最佳方法 - Best way to manage key-value pair in c# 使用Roslyn突出显示C#语法的最佳方法是什么? - What's the best way to highlight C# syntax using Roslyn? 在C#中使用此字符串值的最佳方法是什么? - What is the best way of using this string value in c#? 在C#中查询XML的最佳方法 - 使用LINQ等 - Best way to query XML in C# - using LINQ, etc 在C#中,由班级成员之一搜索班级列表的最佳方法是什么? - In C#, what's the best way to search a list of a class by one of the class's members? C#比较双精度值和一系列值并返回两个文本值的最佳方法是什么 - C# What is the best way to compare a double value to a range of values and return two text values 在 C# 字典中设置所有值的最佳方法是什么<string,bool> ? - What's the best way to set all values in a C# Dictionary<string,bool>? 返回多个枚举值的最佳方法是什么? (Java和C#) - What's the best way to return multiple enum values? (java and C#) 在C#中从矩形数组中提取一维数组的最佳方法是什么? - What's the best way to extract a one-dimensional array from a rectangular array in C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM