This question already has answers here:
What and When to use Tuple? [duplicate]
(5 answers)
Closed 8 years ago.
I was looking at examples online of Tuple but I do not see any ideal use of it.
Meaning, it seems like a place to store variables.
Is there any practical use of Tuple. What I like to do is to pass in a value to the tuple and then have it return back 3 values which are all strings.
A Tuple is counter-part to a List.
While a List stores 0-N of the same type of item, a Tuple store 1-M of (possibly) different-typed items, where N is unbounded and M is statically fixed/defined.
Each of these items can be accessed in a strongly-typed manner by their name (or "index" as it happens to aligned).
They are thus similar to an anonymous type (actually, this is more like a "record" and not a "tuple" because the names can be arbitrarily chosen):
new { _0 = value0, _1 = value1, /* etc, as needed */ }
But the Tuple types are nominatively typed (they are backed by a bunch of different classes, just like Action or Func) and thus a specific Tuple type can be explicitly specified (e.g. in method signatures), which is something an anonymous type cannot be used for.
While I would say that the practical use of Tuples in C# is hampered by the lack of support (e.g. no decomposition, no application, etc.), they are used all the time in languages like Scala. The C# approach is generally to "create a new named type", but introduces the Tuple types as another available tool.
(A big place where Tuples are very useful is in intermediate computations -- but C# has anonymous types, which as seen with LINQ, fulfill this role quite well in most cases where the computations are done within the same method.)
Microsoft .NET 4.0 introduces type called Tuple which is a fixed-size collection of heterogeneously typed data. Like an array, a tuple has a fixed size that can't be changed once it has been created. Unlike an array, each element in a tuple may be a different type, and a tuple is able to guarantee strong typing for each element. This is really handy in scenario otherwise be achieved using custom types or struct.
Tuple s a container. you can store anything in it
For 3 items, it s called Triple. 4 items quadruple and so on.
Essentially you can just stick items in to it.
Here is an example.
The Tuple is a typed, immutable and generic construct. It is a useful container for storing conceptually related data. A simple class with commented members and additional methods is more useful for important things. But the Tuple can be used to store miscellaneous yet related information. Tuple falls short in the field of information hiding. It excels as a useful short-term container.
A practical use-case: let's say you want to pass around a list of structured data between different internal components of a software.
You can either declare a class which represents the structured data. In this case this class has to be dumb ideally, it'll only contain a bunch auto properties. You probably declare this in an interface as an embedded class (but then you have to prefix it with the interface name), or in the same namespace as the interface. At some point this maybe unnecessary plumbing code to define a sole class for this purpose.
Or you can use a tuple. This way you don't have to define a class for all of that, you can still remain type safe. You may loose the advantage of naming the properties, which can be problematic if you have many properties, maybe even from the same type.
More concrete example:
You want to set a column sorting for a TreeListView 3rd party component. You initiate the sorting from the controller object, which calls the right function (SortByColumns) on the view, which calls the function on your wrapper class around the 3rd party component, which calls the 3rd party components' proper functions.
If you define a DTO (dtata transfer object) object:
// Somewhere around an interface
class ColumnSortItem
{
string Caption { get; set; }
SortOrder Order { get; set; }
}
// Other places:
void SortByColumns(IList<ColumnSortItem> pColumnSortItems);
Tuples:
void SortByColumns(IList<Tuple<string, SortOrder>> pColumnSortItems);
I don't say tuples are always the better choice, but notice that we just had to declare a certain order and structure of items. Note, that in this concrete example it's pretty clear what is the string part of the tuple and what is the SortOrder part.
Addition: the actual calls of the function:
DTO
controller.SortByColumns(new List<ColumnSortItem>() {
new ColumnSortItem() { Caption = "Record", Order = SortOrder.Ascending },
new ColumnSortItem() { Caption = "Description", Order = SortOrder.Ascending }
});
Tuple
controller.SortByColumns(new List<Tuple<string, SortOrder>>() {
new Tuple<string, SortOrder>("Record", SortOrder.Ascending),
new Tuple<string, SortOrder>("Description", SortOrder.Ascending)
});
Tuple is a lightweight class to group several items together. It's an alternative to defining a new class any time you want to group two items together.
I find it useful when I want to return multiple items from a single method, but I can't use ref or out parameters.
It seems like it's there for temporary data storage; very localized use. These are occasions when writing your own class is either too time consuming or really not worth it because the data's life time is so short.
The .NET Framework 4 introduce the System.Tuple class for creating tuple objects that contain structured data. It also provides generic tuple classes to support tuples that have from one to eight components .
Here is example in C#
var objTupe = new System.Tuple<string, string, double,long>"Mike","Anderson",29000,9999999999);
Response.Write("Item1 : " + objTupe.Item1);
Response.Write("<br/>Item2 : " + objTupe.Item2);
Response.Write("<br/>Item3 : " + objTupe.Item3);
Response.Write("<br/>Item4 : " + objTupe.Item4);
Related
This question already has answers here:
Return multiple values to a method caller
(28 answers)
Closed 6 years ago.
I need to return 2 values (a string and a point) from a method and I dont really want to use ref/out as the values should stay together.
I was thinking of using a Dictionary<string, Point>.
My question is: Is dictionary a good choice of data structure if it only has one KeyValuePair? Or are there any other suitable options?
If you dont want to create a named class , you can use Tuple to return more than one parameter
Tuple<int, Point> tuple =
new Tuple<int, Point>(1, new Point());
return tuple
You can create your own class. But Tuple<T1, T2> may be convenient. It's just for that sort of thing, when you need to pass around an object containing a few different types.
I'd lean toward creating a class unless it's extremely clear what the tuple is for just by the definition. That way you can give it a name that improves readability. And it can also save a maintenance nuisance if you later determine that there are more than two values. You can just maintain one class instead of replacing Tuple<int, Point> with Tuple<int, Point, Something> in multiple places.
I wouldn't use KeyValuePair because someone looking at it would reasonably assume that there's a dictionary somewhere in the picture, so it would create some confusion. If there are just two values and no dictionary then there is no key.
I'd use a Class or a Structure to store both values. I prefer it to maintain the code and allow you to extend the system in the future.
public class MyData {
public string MyString {get;set;}
public Point MyPoint {get;set;}
}
public class Storage {
public MyData retrieveMyData() {
MyData data = new MyData();
return data;
}
}
Whenever you see this you should pause and think "Should this be an object?"
If it's a one off you can use Tuple but most times you'll come up with a situation where the same parameters are used in conjunction again. By that point you'll wish that you had created an object the first time.
By creating a object for the set of parameters you can give it a name which will increase readability. If you encapsulate the parameters into properties of an object you can also create getter and setter methods, which will allow you to further control access to them and add more functionality if the need comes up in the future.
The main thing is readability. I might call it a NamedPoint which tells anyone reading my code why I've paired the string and the point together. I could later add validation to the name if I wanted it to be a certain length or not start with a number or any number of other things.
I have a predefined data format, which requires me to have an object like this:
settings:{
settingA:'someValueFromSql',
settingB:'someValueFromAD'
settingC:'someValueFromConfigFile',
settingD:'someValueFromReflection',
settingE:42,
...
}
This settings object is in fact a huge mess of data stitched together from many different sources, but this is how the data is expected by the frontend. I'd like to put the "get/process all data from one source" in a function each, and tape the object together in the end.
So I would have one object
sqlSettings:{
settingA:'someValueFromSql',
settingG:'someOtherValueFromSql',
...
}
returned by function a, and an object
adSettings:{
settingB:'someValueFromAD',
settingV:'someOtherValueFromAD',
...
}
returned by function b, and an object
settings includes adSettings, sqlSettings
where, with at most two simple steps, I can "join together" both objects into a flat third object.
Is this possible with fixed-size objects, without using a generic Dictionary, or am I barking up the wrong tree?
(I'm sure this question was already asked on SO, but I guess I don't find the right words)
It's not possible with a "normal" object, but you can do it with an ExpandoObject and the dynamic keyword. But you need at least .net 4.0
dynamic settings = new ExpandoObject();
//If you try to assign a property that doesn't exist, it is added to the object.
settings.SettingA="sfgd"
Anyway I discourage using this approach. why you don't want to use a IDictionary<string, object> or better a IDictionary<string, MyCustomSettingObject>
--------------------UPDATE---------------------
if the only thing that stops you from using a dictionary is the serialization you can implement the IXmlSerializable Interface and ouput the xml you like:
Proper way to implement IXmlSerializable?
If those partial setting objects have fixed size (meaning fixed number of properties), then you can definitely create a flat object with e.g. only properties to fit all the values in. Then to ease your work, you can try to use Automapper to map the partial objects to the "grouped" object.
http://automapper.codeplex.com/
Otherwise, you will have to stick with the dictionary.
If it helps, the following question is in the context of a game I am building.
In a few different places I have the following scenario. There exists a parent class, for this example called Skill, and I have a number of sub-classes implementing the methods from the parent class. There also exists another parent class that we will call Vocation. The skills need to be listed in different sub-classes of Vocation. However, those skills need to be available for anything in the game that uses any given vocation.
My current setup is to have an Enum called Skill.Id, so that Vocation contains a collection of values from that Enum and when an entity in the game takes on that Vocation the collection is passed into another class, called SkillFactory. Skill.Id needs a new entry every time I create a new Skill sub-class, as well as a case in the switch block for the new sub-classes' constructor.
i.e.:
//Skill.Id
Enum{FireSkill,WaterSkill,etc}
//SkillFactory
public static Skill Create(Skill.Id id)
{
switch(id)
{
case Skill.Id.FireSkill:
return new FireSkill();
//etc
}
}
This works perfectly fine, but using the enum and switch block as a go between feels like more overhead than I need to solve this problem. Is there a more elegant way to create instances of these Skill sub-classes, but still allows Vocation to contains a collection identifying the skills it can use?
Edit: I am fine throwing out the enum and associated switch block, so long as Vocation can contain a collection that allows arbitrary instantiation of the Skill sub-classes.
You can make a Dictionary<Skill.Id, Func<Skill>> and use it to instantiate.
In the constructor:
Dictionary<Skill.Id, Func<Skill>> creationMethods = new Dictionary<Skill.Id, Func<Skill>>();
public SkillFactory()
{
creationMethods.Add(Skill.Id.FireSkill, () => new FireSkill());
creationMethods.Add(Skill.Id.WaterSkill, () => new WaterSkill());
}
Then, your Create method becomes:
public static Skill Create(Skill.Id id)
{
return creationMethods[id]();
}
Granted, this isn't much better - except that it does allow you to extend this to other functionality that's per ID without duplicating the switch block if that becomes a requirement. (Just put more into the value side of the Dictionary.)
That being said, in the long run, getting rid of the enum entirely can be a good benefit for extensibility. This will require a more elaborate change, however. For example, if you used MEF, you could import a set of SkillFactory types at runtime and associate them to a name (via metadata) via a single ImportMany. This would allow you to add new Skill subclasses without changing your factory, and refer to them by name or some other mechanism.
if this creation function is going to be so used that a "case" will produce overhead, dictionary with enums keys will generate a lot of garbage.
In the context of a xna game, it can be worse than the "case".
"If you use an enum type as a dictionary key, internal dictionary operations will cause boxing. You can avoid this by using integer keys, and casting your enum values to ints before adding them to the dictionary." Extracted from here
You can use a simple array and cast enum to int for indexing:
Enum {FireSkill=0,WaterSkill=1,etc}
Func<Skill>[] CreationMethods = new Func<Skill>()
{
() => new FireSkill(),
() => new WaterSkill(),
}
I have three different classes:
Task
Order
Transmission
Each class have properties with different types. Also, there is a possibility to attach data that represented by custom fields (implemented by an array of IField, where IField can be text field or list field). Each custom field have a name that represent the name of the attached data property.
I need to convert between each class to another:
Task -> Order
Order -> Transmission
Transmission -> Task
Transmission -> Order
Order -> Task
Task -> Transmission
for that I created:
Static class of static keys where each key represents the name of
the property.
"DataObject" that holds a dictionary of a property name and an object as its value.
Each class (Task, Order, Transmission) implements IDataShare interface:
public interface IDataShare
{
DataObject ToDataObject();
void FromDataObject(DataObject data);
}
For example, task objects with the following properties:
WorkerId:5
CustomerId:7
VehicleId:null
StartDate:null
And with the following custom fields:
Subcontractor: {listId:5, Value:4} (this is list field)
delivery Note: "abc" (this is text field)
will be convert to the following dictionary:
{"WorkerId", 5}
{"CustomerId", 7}
{"VehicleId", null}
{"StartDate", null}
{"Subcontractor", {listId:5, Value:4}}
{"delivery Note", "abc"}
the string keys "WorkerId", "CustomerId", "VehicleId", "StartDate" were taken from static class that contains string consts where "Subcontractor" and "deliveryNote" are the names of the custom fields the user added (I don't know which fields the user might add so I just use the field name).
When I fill an object using DataObject I have to verify the name of the property is the same as the name of the key and also verify the value is correct (string cannot inserted into long).
In addition, custom list field (subcontractor) can't have only itemId as a value because when I have to verify that the listId of the custom field in the object is the same with the listId of the customField in the DataObject.
I have many problems about knowing the type of the value. I always have to use "X is Y" if statements of "X as Y" statements. In addition, I have to remember how to store the type of the value when implementing IDataShare interface which makes the work harder.
Can anyone help me think about constraint I can add to the conversion proccess from an object to DataObject? Can anyone help me improve this method of converting objects?
Thanks!
UPDATE
I want to explain a point. My biggest problem is that there are several ways to translate each property/custom field so I need to remember the type of the value in DataObject. For example, in Transmission class I have VehicleId property. I want to convert Task object with custom field with the name "VehicleId" to Transmission. All I want is that Task's custom field VehicleId's value will be converted into the VehicleId property of Transmission. But, because it is custom field - as I wrote before - there is a way I store custom field that based on a list: {listId:5, Value:4}. Now, in the conversion proccess (FromDataObject in Transmission) in case the DataObject has "VehicleId" key, I have to check whether the value is long (vehicle id as property) or IListField (vehicle id as custom list field).
those type checking really makes mess.
Well, if the number of classes you're converting between is really as limited as you've said, may I suggest just writing casting operators for your classes?
http://msdn.microsoft.com/en-us/library/xhbhezf4%28v=VS.100%29.aspx
It seems like the amount of logic that you're putting into the conversion is enough to warrant something like this.
On the other hand, it seems like there is a base set of fields being used across the different objects and you're just stuffing them into an untyped dictionary. If the fields are common across all types, could you use a conversion to a strongly typed common object?
Which also begs the question: could you use a common base class object?
If you have options of modifying the Task, Order, and Transmission definitions, I'd take a look at them again. This sort of scenario seems like a "code smell".
If I understand this correctly ToDataObjectis basically a serializer and FromDataObject is a deserializer. If the data contained by these object is type compatible, then it seems that the very act of serializing it into untyped data is the source of your problem. Why do this, instead of just keeping the data in its native format?
If you need to use an adapter because there are incompatibilities between the objects that can't be resolved for some reason, I would think that you can make one that at least keep the data in its native structures instead of serializing everything to a string. A dictionary in C# can contain anything, at a minimum you could be using a Dictionary<string,object>.
It's also unclear what all this verification is about - why would data be incompatible, if you are mapping properties of the same data types? E.g. assuming that this is an internal process, under what circumstance could (e.g.) a string from one object be trying to be assigned to a long in another object? Seems that would only be necessary if the data were strongly typed in one object, but not in another.
Have you considered using generics?
If Task, Order and Transmission all inherit from a base class like Property, then you could expose a common method for getting the values you need.
GetMyValue() where T : Property
It's not very clear what you are trying to achieve.
In a question about Best practices for C# pattern validation, the highest voted answer
says:
I tend to perform all of my validation in the constructor. This is a must because I almost always create immutable objects.
How exactly do you create an immutable object in C#? Do you just use the readonly keyword?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
Would it look like below?
public partial readonly Person
{
public Person()
}
The interesting question here is your question from the comments:
What kind of object would you have that you do not need to modify the values at some point? I'm guessing not a model class, correct? I've had to change the name of a person in my database - this wouldn't fit with this idea.
Well, consider things that are already immutable. Numbers are immutable. Once you have the number 12, it's 12. You can't change it. If you have a variable that contains 12, you can change the contents of the variable to 13, but you are changing the variable, not the number 12.
Same with strings. "abc" is "abc", and it never changes. If you have a variable that contains "abc", you can change it to "abcd", but that doesn't change "abc", that changes the variable.
What about a list? {12, "abc"} is the list that is 12 followed by "abc", and that list never changes. The list {12, "abcd"} is a different list.
And that's where things go off the rails. Because in C# you can do it either way. You can say that there is referential identity between those two lists if lists are allowed to mutate their contents without changing their identity.
You hit the nail right on the head when you talk about the "model". Are you modeling something that changes? If so, then it is possibly wise to model it with a type that changes. The benefit of that is that the characteristics of the model match the system being modeled. The down side is that it becomes very tricky to do something like a "rollback" functionality, where you "undo" a change.
That is, if you mutate {12, "abc"} to {12, "abcd"} and then want to roll back the mutation, how do you do it? If the list is immutable you just keep around both values and choose which one you want to be the "current" value. If the list is mutable then you have to have the undo logic keep around an "undo function" which knows how to undo the mutation.
As for your specific example, you certainly can create an immutable database. How do you change the name of someone in your immutable database? You don't. You create a new database that has the data you want in it. The trick with immutable types is to do so efficiently, without copying billions of bytes. Immutable data structure design requires finding clever ways to share state between two nearly-identical structures.
Declaring all fields readonly is a good step towards creating an immutable object, but this alone is not sufficient. This is because a readonly field can still be a reference to a mutable object.
In C# immutability is not enforced by the compiler. You just have to be careful.
This question has two aspects:
Immutable type when you instantiate object
Immutable type when EF instantiate object
The first aspect demands sturcture like this:
public class MyClass
{
private readonly string _myString;
public string MyString
{
get
{
return _myString;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
}
Now the problem - EF. EF requires parameterless constructor and EF must have setters on properties. I asked very similar question here.
Your type must look like:
public class MyClass
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
private set
{
_myString = value;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
// Not sure if you can change accessibility of constructor - I can try it later
public MyClass()
{}
}
You must also inform EF about private setter of MyString property - this is configured in properties of enitity in EDMX file. Obviously there will be no validation when EF will materialize objects from DB. Also you will not be able to use methods like ObjectContext.CreateObject (you will not be able to fill the object).
Entity Object T4 template and default code generation create factory method CreateMyClass instead of constructor with paremeters. POCO T4 template doesn't generate factory method.
I didn't try this with EF Code first.
An immutable value object is a value object that cannot be changed. You cannot modify its state, you have to create new ones
Check out Eric Lippert's blog:
Kinds of Immutability
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability
Have a look at
Immutable object pattern in C# - what do you think?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
It wouldn't work in this context because EF requires the properties of the entity class be public otherwise it can't instantiate it.
But you're welcome to use immutable objects further in your code.
C# 9 is coming up with new feature names as Record. Init-only properties are great if you want to make individual properties immutable. If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record:
public data class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
The data keyword on the class declaration marks it as a record.
Reference: https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#records
#Eric Lippert Good comment, but in addition in answer to the question:
What kind of object would you have that you do not need to modify the
values at some point? I'm guessing not a model class, correct? I've
had to change the name of a person in my database - this wouldn't fit
with this idea.
Let's say you have a large datastructure and you want to query its information, but it's changing all the time. You need some kind of locking system to make sure that you don't say try and count the total in the system while somebody is depositing something from one place to another. (Say a warehouse management system)
And that's hard to do because these things always affect things in unexpected ways, the data changing under your feet.
What if you could freeze your large datastructure when you're not updating it, so that no memory can be altered and it is paused at a consistent state? Now when you want to change it again you have to copy the datastructure to a new place, and it's fairly large, so that's a downside, but the upside is you won't have to lock anything because the new copy of the data goes unshared until it has been updated. This means anyone at any point can read the latest copy of the datastructure, doing complex things.
So yep very useful concept if you hate dealing with concurrency issues and don't have too much data to deal with. (E.g. if 1MB of data and updating 10/sec that's 10MB of data being copied)