English 中文(简体)
C# 3.0 Tuple Equivalents (for poor men)
原标题:

I find myself occasionally in C# 3.0 looking for ways to simulate the notion of a tuple. Over time I ve had various "poor man s" implementations, here are a few of them:

Basic Object Array:

object[] poorTuple = new object[]{foo,bar,baz}; // basic object array

More Strongly Typed, HoHoHo...

KeyValuePair<TypeA, KeyValuePair<TypeB, TypeC>> poorTuple;

Implementing a class that can use type inference (lifted from Functional Programming for the Real World)

public static class Tuple{
  public static Tuple<T1, T2> Create<T1 foo, T2 bar>{
    return new Tuple<T1, T2>(foo, bar);
  }
}
// later: 
var data = Tuple.Create("foo", 42);

Questions:

  1. Any other ways to have a poor man s tuple in C# 3.0 (or language of choice that lacks the data structure).

  2. What is the best way to get a tuple in C# 3.0 - if anyone has a library recommendation it is welcome.

  3. At what point (yes, generalize for me) does it make sense to create a specific type rather than something like a list or tuple? (looking for rules of thumb)

最佳回答

You can create anonymous types which function similarly to tuples, except with useful names:

var itemsWithChildCounts 
    = myObjects.Select(x => new { Name = x.Name, Count = x.Children.Count() });
问题回答

Here is the code for a generic tuple taken from Bill Wagner s article in the April 2007 edition of Visual Studio Magazine.

public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>>
{
    private readonly T1 first;
    public T1 First
    {
        get { return first; }
    }

    private readonly T2 second;
    public T2 Second
    {
        get { return second; }
    } 

    public Tuple(T1 f, T2 s)
    {
        first = f;
        second = s;
    }

    #region IEquatable<Tuple<T1,T2>> Members
    public bool Equals(Tuple<T1, T2> other)
    {
        return first.Equals(other.first) && 
            second.Equals(other.second);
    }

    public override bool Equals(object obj)
    {
        if (obj is Tuple<T1, T2>)
            return this.Equals((Tuple<T1, T2>)obj);
        else
            return false;
    }

    public override int GetHashCode()
    {
        return first.GetHashCode() ˆ second.GetHashCode();
    }
    #endregion
}

For 1 - 2: I prefer implementing your own tuple class. The implementation you stole is a decent one. It should work well.

For 3: Here s my rule of thumb - As soon as you re going to reuse this functionality in multiple methods (with the same types having the same meaning), or if you use it in any public API, I think it s time to implement a "real" class with your specific types.

  1. The "Implementing a class" method is as good as it s going to get (and it should be in the next version of .NET anyway)
  2. No idea, I keep them in my own personal library of classes for now.
  3. I d consider creating a proper class for them as soon as they get exposed to the public (i.e. when they are no longer used just to store related values for a class internally).

Since you asked for an opinion, mine would be to always create a type--I can t figure out a reason not to.

More often than not you can find that you actually needed the type (the main use is either to store two items in a collection or return two items from a method call--in both cases if the items aren t closely related, you re probably doing something wrong).

I think it s good to create a new type when it makes sense to introduce a new value set into your program. For example, if you are writing a complex calculator, then make a complex number type. If you really just want to "glue" a few variables together for a moment, then a tuple is probably a better choice. Let s say you ve got a simple function that gathers two numbers from the console... you might do something like:

static void GetNumbers(out int x, out int y) { ... }
...
int x, y;
GetNumbers(out x, out y);

I think it usually makes sense when a "getter" function has a return value but in this case it doesn t because I can t really have two return values. I could go and make a new type called TwoNumbers and use that but I think this quickly becomes more of a problem than a solution. If C# had tuples I may be able to do something like the following:

static (int, int) GetNumbers() { ... }
...
int x, y;
(x, y) = GetNumbers();

Now the really interesting question is: although C# doesn t have this feature am I able to implement it myself with a library? The code you suggest is a start but won t allow me to assign like I ve done in the second example. I m not sure about C# but you can get really darn close to this in C++ by using the fact that a function call can be the left operand to the assignment operator when it s return value is a reference type. Consider the following:

// this class is implemented much like yours only with C++
template<typename T1, typename T2> class tuple { ... }
...
template<typename T1, typename T2> tuple<T1, T2>& tie(T1 a, T2 b) { ... }
...
template<typename T1, typename T2> tuple<T1, T2> get_numbers() { ... }
...
int x, y;
tie(x, y) = get_numbers();

I d say that is pretty darn close... instead of (x, y) = we have tie(x, y) =. If you are interested in implementation details, I ll refer you to the TR1 library where I first learned about this:

http://www.boost.org/doc/libs/1_41_0/libs/tuple/doc/tuple_users_guide.html#tiers

So to bring all this back to C# 3.0... we can certainly create a generic tuple class as you ve shown, but can we create a function like tie to "unpack" the tuple in C#? I haven t tried it, sounds like fun. Without something like that, I d be reluctant to let a C# tuple library proliferate through my code.

I dont like type inference in C# since it is abused to much for shorter writing. Of course it is a very cool feature, but people abuse it IMHO like in this case.

In this case i would specify the type explicitly to avoid confusions about the type (i.e. perhaps 42 is a long, or a byte or a short).

So why not having a simple tuple class, which can be implemented in just a few lines. And if you re lazy you can even write some extension methods for your tuple class. This makes life easier but also cleaner.

Dont see the point of having a "fancy" tuple class instead of the generic one you presented (except for the type inference).





相关问题
Converting a Tuples List into a nested List using Python

I want to convert a tuples list into a nested list using Python. How do I do that? I have a sorted list of tuples (sorted by the second value): [(1, 5), (5, 4), (13, 3), (4, 3), (3, 2), (14, 1), (...

Translating python dictionary to C++

I have python code that contains the following code. d = {} d[(0,0)] = 0 d[(1,2)] = 1 d[(2,1)] = 2 d[(2,3)] = 3 d[(3,2)] = 4 for (i,j) in d: print d[(i,j)], d[(j,i)] Unfortunately looping ...

Is there a tuple data structure in Python

I want to have an 3 item combination like tag, name, and list of values (array) what is the best possible data structure to store such things. Current I am using dictionary, but it only allows 2 ...

C# 3.0 Tuple Equivalents (for poor men)

I find myself occasionally in C# 3.0 looking for ways to simulate the notion of a tuple. Over time I ve had various "poor man s" implementations, here are a few of them: Basic Object Array: object[] ...

F# match active pattern as expanded tuple

I get the following error in diff with a red squiggle under Subset. Type mismatch. Expecting a Range -> Choice but given a Range * Range -> Choice Is there some sort of type annotation I can ...

Why can t I sort this list?

statlist = [( abc ,5,1), ( bzs ,66,1), ... ] sorted(statlist, key=lambda x: int(x[1])) I want to sort it by the integer largest to smallest. In this case, 5 and 66. But it doesn t seem to be working.

Why can t I join this tuple in Python?

e = ( ham , 5, 1, bird ) logfile.write( , .join(e)) I have to join it so that I can write it into a text file.

热门标签