Coffeehouse Thread

32 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

How are you using Tuple in code?

Back to Forum: Coffeehouse
  • User profile image
    BitFlipper

    Or maybe a bit cleaner way to do it...

    public class Operation
    {
        public <int RunCount, TimeSpan MaxTime, TimeSpan MinTime, TimeSpan AvgTime> Statistics
        {
            get
            {
                lock (m_lock)
                {
                    var retVal = new return();
                    retVal.RunCount = m_runs;
                    ///etc...
    
                    return retVal;
                }
            }
        }
    }

    The "new return()" statement means to instantiate whatever the return type of the current method is. The compiler should be able to infer this from the current method's return type just like it can infer a type when assigning to var from the return of a method. Also there is no Tuple type, just an anonymous type as the return type.

    I'm no LINQ expert but isn't this very similar to how LINQ does its magic?

  • User profile image
    Ion Todirel

    I don't use Tuple that much, but I use Pair a lot. I like the Tuple class in C++, in particular, a lot. Unlimited number of types, and the access is thru std::get<n>(tuple), nicer IMO than tuple.Item4.

  • User profile image
    Dr Herbie

    , SteveRichter wrote

    *snip*

    how else do you return multiple values from a method? out arguments are a bit clunky in that they require the "out" modifier and all the out arguments have to be declared and specified on the call. Declaring a class to be returned is probably ideal, but takes time to code and is another class you have to add to the project.

    Having thought about this for a while, I'm tempted to dump Tuple<> altogether for private method calls and just use anonymous types.  I already create specific structs for public methods (as it's easier for other developers to understand the shape of the data being returned); adding another struct to our 250,000+ lines of code isn't a big deal if it improved clarity.

    Herbie

  • User profile image
    MasterPi

    , wkempf wrote

    int index, string name = FindMostExpensiveProduct(); // dumb example

    I miss this type of statement from SML.

    (x,j) = findChip(row,col)

    It'd be cool syntactic sugar if ( ... , ... ) could automatically construct a tuple.

    protected (Location, Person) HelpMe(Person p, EmergencyType x) { ... return (goHere, talkToThisPerson); }

    Maybe it's only reasonable in a functional context...

    Also, why did they stop at 8 and not 9? Tongue Out

  • User profile image
    Bass

    @cbae:

    Thanks a lot. That method signature made me puke. I'm going to have to buy dinner again. Make sure to tag such examples with NSFL in the future.

  • User profile image
    cbae

    @Bass: You're welcome! I'm glad to help out your local economy, wherever it may be.

  • User profile image
    Dr Herbie

    , Dr Herbie wrote

    *snip*

    Having thought about this for a while, I'm tempted to dump Tuple<> altogether for private method calls and just use anonymous types.  I already create specific structs for public methods (as it's easier for other developers to understand the shape of the data being returned); adding another struct to our 250,000+ lines of code isn't a big deal if it improved clarity.

    Herbie

    I'm surprised that no-one jumped on me for this -- turns out you cannot return anonymous types ... so Tuple<> it is ...

    Herbie

  • User profile image
    cbae

    , Dr Herbie wrote

    *snip*

    I'm surprised that no-one jumped on me for this -- turns out you cannot return anonymous types ... so Tuple<> it is ...

    Herbie

    Well, I did post this: Wink

    If the objects in question aren't going to be passed around, anonymous types are far better at self-documenting.

  • User profile image
    Ion Todirel

    @BitFlipper:

    , BitFlipper wrote

    Or maybe a bit cleaner way to do it...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class Operation
    {
        public <int RunCount, TimeSpan MaxTime, TimeSpan MinTime, TimeSpan AvgTime> Statistics
        {
            get
            {
                lock (m_lock)
                {
                    var retVal = new return();
                    retVal.RunCount = m_runs;
                    ///etc...
     
                    return retVal;
                }
            }
        }
    }

    The "new return()" statement means to instantiate whatever the return type of the current method is. The compiler should be able to infer this from the current method's return type just like it can infer a type when assigning to var from the return of a method. Also there is no Tuple type, just an anonymous type as the return type.

    I'm no LINQ expert but isn't this very similar to how LINQ does its magic?

    the syntax you are proposing is very similar to GoLang multiple return values:

    func (file *File) Write(b []byte) (n int, err Error)

  • User profile image
    Adam​Speight2008

    @Dr Herbie: I'm sure you can return anonymous types, if the return type in the signature is T.

    Subsequent variables have to be typed T or var, the same goes for input parameters.

     But in practice it usually better to have a "concrete" type instead.

  • User profile image
    Bigfellahull

    I find them useful when using a composite key dictionary.

    var dictionary = new Dictionary<Tuple<int, string>, string>();
    dictionary.Add(Tuple.Create(3, "SomeKey"), "Value");

     

  • User profile image
    Bas

    I'm also debating the "create an actual struct" versus "use a Tuple" thing. There's a web service that returns a bunch of strings with their indexes. However, it returns translated strings for various locales. I could create some sort of LocaleKeyPair struct containing a Locale property and a Key property, and use that:

    var valuesForAllLocales = new Dictionary<LocaleKeyPair, string>();
    //...
    var value = valuesForAllLocales[new LocaleKeyPair(currentLocale, key)];

    Or I could use a Tuple:

    var valuesForAllLocales = new Dictionary<Tuple<string, string>, string>();
    //...
    var value = valuesForAllLocales[Tuple.Create(currentLocale, key)];

    The former is more self-documenting and avoids the ugly <<>> nested generics thing (which FxCop complains about), but that quickly leads to a project filled with semi-useful XYPair structs, which clutters up your library fast. I'm leaning toward the former, but I'm not sure. Any ideas?

  • User profile image
    evildictait​or

    , Bas wrote

    I'm also debating the "create an actual struct" versus "use a Tuple" thing. 

    ...

     

    The former is more self-documenting and avoids the ugly <<>> nested generics thing (which FxCop complains about), but that quickly leads to a project filled with semi-useful XYPair structs, which clutters up your library fast. I'm leaning toward the former, but I'm not sure. Any ideas?

    My take on it is that Tuple<A,B> is useful within projects to speed up dumb coupled variables, but they should never be exposed across projects (i.e. over an API boundary) because it's not descriptive enough as to what the two items are. For those you should always be creating a manual class with two elements. This gives you:

    * Useful names, instead of Item1/Item2.
    * Somewhere to add Item3 later when you need it, without needing huge source-level changes in both your code and your API consumer's code.
    * Somewhere to add useful methods (like, say, float CartesianDistance() for XYCoord instead of nothing on a Tuple<float, float>).
    * A better overloaded ToString() method to make life easier when debugging
    * Stronger types. You can't confuse an XYCoord with an XYSize, but if they're both Tuple<float, float> you might forget.
    * You can add XML comments to your type, but you can't add them to a generically parameterized class that you don't control, so XYCoord will be more useful to your API consumers than Tuple<X, Y> would be.

    My 2c.

  • User profile image
    Ion Todirel

    , Adam​Speight2008 wrote

    @Dr Herbie: I'm sure you can return anonymous types, if the return type in the signature is T.

    Subsequent variables have to be typed T or var, the same goes for input parameters.

     But in practice it usually better to have a "concrete" type instead.

    That's not how templates generics works in C#, you have to declare the contract prior.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.