20

I frequently find myself having a need to create a class as a container for some data. It only gets used briefly yet I still have to create the class. Like this:

public class TempObject
{
    public string LoggedInUsername { get; set; }
    public CustomObject SomeCustomObject { get; set; }
    public DateTime LastLoggedIn { get; set; }
}


public void DoSomething()
{
    TempObject temp = new TempObject
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah blah,
        LastLoggedIn = DateTime.Now
    };
    DoSomethingElse(temp);
}

public void DoSomethingElse(TempObject temp)
{
    // etc...
}

Usually my temporary objects have a lot more properties, which is the reason I want to group them in the first place. I wish there was an easier way, such as with an anonymous type. The problem is, I don't know what to accept when I pass it to another method. The type is anonymous, so how am I supposed to accept it on the other side?

public void DoSomething()
{
    var temp = new
    {
        LoggedInUsername = "test",
        SomeCustomObject = //blah blah,
        LastLoggedIn = DateTime.Now
    };
    // I have intellisense on the temp object as long as I'm in the scope of this method.
    DoSomethingElse(temp);
}

public void DoSomethingElse(????)
{
    // Can't get my anonymous type here. And even if I could I doubt I would have intellisense.
}

Is there a better way to create a temporary container for a bunch of different types, or do I need to define classes every time I need a temporary object to group things together?

Thanks in advance.

CatDadCode
  • 58,507
  • 61
  • 212
  • 318
  • There are **open source library** to do that check [this](http://stackoverflow.com/questions/11446711/dummy-objectlist-generator-for-unit-testing) and [this](http://stackoverflow.com/questions/6625490/c-sharp-library-to-populate-object-with-random-data) post's. hope helps someone. – Shaiju T May 06 '17 at 12:58
  • You could use **internal** modifier on your TempObject and related members instead of public, this way that type will not available from other assemblies. – Lorenzo Delana Aug 20 '20 at 09:21

5 Answers5

35

Tuple may be the solution you're looking for.

public void DoSomething() 
{
    var temp = Tuple.Create("test", "blah blah blah", DateTime.Now);
    DoSomethingElse(temp);
}

public void DoSomethingElse(Tuple<string, string, DateTime> data)
{
    // ...
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • Interesting. Yes this would be more along the lines of what I'm looking for. – CatDadCode Aug 10 '11 at 23:02
  • 1
    KeyValuePair on pre .NET 4.0 although it only lets you have two 'members'. – Dmitry Aug 10 '11 at 23:07
  • 7
    I am going with this answer because it really is exactly what I was asking for. However, I don't really intend to use it because after putting it in practice I decided it wasn't very readable. Creating a custom transfer object is always well-named and very readable to anyone examining the code. I may find a use for Tuple sometime, but the slight overhead of a class just makes things easier to follow and remember. – CatDadCode Aug 10 '11 at 23:15
  • Great answwer, I think. In DoSomethingElse how do I access the individual componenents of the Tuple? – paparazzo Aug 10 '11 at 23:21
  • There are **open source library** to do that check [this](http://stackoverflow.com/questions/11446711/dummy-objectlist-generator-for-unit-testing) and [this](http://stackoverflow.com/questions/6625490/c-sharp-library-to-populate-object-with-random-data) post's. hope helps someone. – Shaiju T May 06 '17 at 12:58
6

The rules state that

You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type. Similarly, you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type.

Personally, I would just bite the bullet on this one to preserve compile time integrity.

Neil Moss
  • 6,598
  • 2
  • 26
  • 42
2

The Tuple is the clean way to go, but just to let you know that C# doesn't let you down even otherwise and to answer the question, this is how DoSomethingElse could look like:

private static void DoSomething(object temp)
        {
            var typedTemp = CastToType(temp, new
                            {
                                LoggedInUsername = "dummy",
                                SomeCustomObject = "dummy",
                                LastLoggedIn = DateTime.Now
                            });

            Console.WriteLine(typedTemp.LastLoggedIn);
        }

private static T CastToType<T>(object obj, T type)
        {
            return (T) obj;
        }

PS: Don't -1, I won't use this, I don't ask you to use this :)

manojlds
  • 290,304
  • 63
  • 469
  • 417
0

You can pass around anonymous types by declaring the parameter dynamic under C# 4. That said, I would not recommend this except in private methods. You lose type-safety, IntelliSense, and readability.

You could also use non-generic container classes such as ArrayList. But then you're back to casting, which is why we got generics in the first place.

Personally I'd create the class. Look to see if there's an abstraction that covers all your types and declare that as an interface, then use a generic container of that type.

TrueWill
  • 25,132
  • 10
  • 101
  • 150
  • I am aware of the dynamic keyword but that totally takes away intellisense and removes compile-time type checking. If it were dynamic I could access `temp.NonExistentProperty` and would not get a compiler error. That is absolutely horrid. – CatDadCode Aug 10 '11 at 23:02
  • @Alex: I agree, which is why I don't recommend it for this use. But the meaning of tuple.Item1 isn't obvious to a reader, so that also has disadvantages. – TrueWill Aug 10 '11 at 23:11
  • I agree as well. Tuple seemed perfect at first but I'm starting to change my mind for readability's sake. – CatDadCode Aug 10 '11 at 23:13
  • @Alex if you want the compiler to be able to check types then how do you expect it to do that if you don't provide a class? – paparazzo Aug 10 '11 at 23:24
  • @BalamBalam Tell me, why do you think I posted this question? Is it A) I already knew the answer, or B) I didn't know the answer. You have 30 seconds.....go. *---plays jeopardy theme song---* – CatDadCode Aug 10 '11 at 23:29
-2
    public class GenericObjs
    {
        private List<object> objs = new List<object>();
        public List<object> Objs { get { return objs; } set { objs = value; } }
        public GenericObjs(List<object> Objs) { objs = Objs; }
    }

You could include List String and a constructor for List String ...

I just don't come across the need for throw away classes. If the business object has structure then a class is the way to define and enforce that structure and it is not much code.

paparazzo
  • 44,497
  • 23
  • 105
  • 176