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.
Related
The IEnumerable in question is a list of an object containing filenames and properties relating to those file names, and the string is a directory name, such as "C:\Test\Testing". My goal is to store these two pieces of data together so that they're 'linked', in a sense, which should make them easier to use together, as the IEnumerable will become the source for a DataGrid, and the string the text of a label stating the current directory.
How would I go about achieving this? I initially thought of a dictionary, but that doesn't seem to work here. I need to be able to grab the 'top-most' item, so to speak, whenever a button is pressed, and dictionaries are, I believe, unordered.
While the accepted answer works, I would recommend creating a class for this, rather than using a KeyValuePair:
public class FilesInDirectory
{
public string Directory { get; set; }
public IEnumerable<string> FileNames { get; set; }
}
In OOP you should strive to avoid primitive obsession. A KeyValuePair is a kind of primitive, as it doesn't convey any meaning and can't be extended.
Meaning: When you're iterating over the list and dealing with item.Key and then iterating over item.Value, things will get confusing - far less so than item.Directory and item.FileNames
Extension: You will want to define some methods that extract data from these items, or process them in some way - usually, these methods are better off on the data item itself. For example you might want to get a list of actual file objects. With a KeyValuePair, you will have to define that method on some other class, whereas it actually fits right at home on FilesInDirectory.GetFiles()
How about a List<KeyValuePair<IEnumerable, string>>?
var list = new List<KeyValuePair<IEnumerable, string>>();
list.Add(new KeyValuePair<IEnumerable, string>(data, path));
If that sounds too awkward for you, feel free to use a custom class instead.
Feel free to use a Queue<>, Stack<> or anything else that fits your needs, KeyValuePair can be used with any collection type.
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);
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)
I have a function that identify coordinates on a page, and I am returning them as a
Dictionary<int, Collection<Rectangle>> GetDocumentCoordinates(int DocumentId)
However, later I need information about each page - if it was validated, what is the page resolution, color/bw, etc. I could create another function and run through pretty much the same result set as the previous function and get that information.
Dictionary<int, PageInfo> GetDocumentAttributes(int DocumentId)
Another alternative would be to add a ref parameter so I can get these values back.
Dictionary<int, Collection<Rectangle>> GetCoordinates(int DocumentId, ref Dictionary<int, PageInfo> PageAttributes)
Yet another alternative is to create an encompassing class that contains the Dictionary and the page information:
class DocumentInfo
{
Dictionary<int, Collection<Rectangle>> Coordinates { get; set;}
Dictionary<int, PageInfo> PageAttributes { get; set; }
}
and then define:
DocumentInfo GetDocumentInfo(int DocumentId);
I'm leaning towards the last option, but your insights are very much appreciated.
The last option is definitely the best. I've found that, when taking or returning complex data with multiple meanings, creating a complex type to encapsulate this data is the best practice for a number of reasons.
First, your return data probably will change as your design changes. Encapsulating this data in an object allows you to alter what it carries and how your methods operate on this data without altering the interfaces of your objects. Obviously, your data object shouldn't implement an interface; at most, have a base class with the minimum interface and then pass references to the base around.
Second, you may find your data gets complex to the point where you will need to perform validation on it. Rather than have this validation in all the methods of your classes where you act upon this data, you can easily wrap this up in the data class. Single responsibility, etc.
It seems like you need a lot of data out. The last option should be fine, and is extensible; it you wanted (to simplify the Dictionary<,> usage), you could encapsulate things a bit more, but the fact that C# doesn't directly support named indexed properties means you'd need a few classes, unless you just wrap with methods like:
class DocumentInfo {
Dictionary<int, Collection<Rectangle>> rectangles = ...
public Collection<Rectangle> GetRectangles(int index) {
return rectangles[index]; // might want to clone to
// protect against mutation
}
Dictionary<int, PageInfo> pages = ...
public PageInfo GetPageInfo(int index) {
return pages[index];
}
}
I'm not quite clear what the int is, so I can't say whether this is sensible (so I've just left it alone).
Also - with the first option, you probably wouldn't need ref - it would be sufficient to use out.
So if I have a method of parsing a text file and returning a list of a list of key value pairs, and want to create objects from the kvps returned (each list of kvps represents a different object), what would be the best method?
The first method that pops into mind is pretty simple, just keep a list of keywords:
private const string NAME = "name";
private const string PREFIX = "prefix";
and check against the keys I get for the constants I want, defined above. This is a fairly core piece of the project I'm working on though, so I want to do it well; does anyone have any more robust suggestions (not saying there's anything inherently un-robust about the above method - I'm just asking around)?
Edit:
More details have been asked for. I'm working on a little game in my spare time, and I am building up the game world with configuration files. There are four - one defines all creatures, another defines all areas (and their locations in a map), another all objects, and a final one defines various configuration options and things that don't fit else where. With the first three configuration files, I will be creating objects based on the content of the files - it will be quite text-heavy, so there will be a lot of strings, things like names, plurals, prefixes - that sort of thing. The configuration values are all like so:
-
key: value
key: value
-
key: value
key: value
-
Where the '-' line denotes a new section/object.
Take a deep look at the XmlSerializer. Even if you are constrained to not use XML on-disk, you might want to copy some of its features. This could then look like this:
public class DataObject {
[Column("name")]
public string Name { get; set; }
[Column("prefix")]
public string Prefix { get; set; }
}
Be careful though to include some kind of format version in your files, or you will be in hell's kitchen come the next format change.
Making a lot of unwarranted assumptions, I think that the best approach would be to create a Factory that will receive the list of key value pairs and return the proper object or throw an exception if it's invalid (or create a dummy object, or whatever is better in the particular case).
private class Factory {
public static IConfigurationObject Factory(List<string> keyValuePair) {
switch (keyValuePair[0]) {
case "x":
return new x(keyValuePair[1]);
break;
/* etc. */
default:
throw new ArgumentException("Wrong parameter in the file");
}
}
}
The strongest assumption here is that all your objects can be treated partly like the same (ie, they implement the same interface (IConfigurationObject in the example) or belong to the same inheritance tree).
If they don't, then it depends on your program flow and what are you doing with them. But nonetheless, they should :)
EDIT: Given your explanation, you could have one Factory per file type, the switch in it would be the authoritative source on the allowed types per file type and they probably share something in common. Reflection is possible, but it's riskier because it's less obvious and self documenting than this one.
What do you need object for? The way you describe it, you'll use them as some kind (of key-wise) restricted map anyway. If you do not need some kind of inheritance, I'd simply wrap a map-like structure into a object like this:
[java-inspired pseudo-code:]
class RestrictedKVDataStore {
const ALLOWED_KEYS = new Collection('name', 'prefix');
Map data = new Map();
void put(String key, Object value) {
if (ALLOWED_KEYS.contains(key))
data.put(key, value)
}
Object get(String key) {
return data.get(key);
}
}
You could create an interface that matched the column names, and then use the Reflection.Emit API to create a type at runtime that gave access to the data in the fields.
EDIT:
Scratch that, this still applies, but I think what your doing is reading a configuration file and parsing it into this:
List<List<KeyValuePair<String,String>>> itemConfig =
new List<List<KeyValuePair<String,String>>>();
In this case, we can still use a reflection factory to instantiate the objects, I'd just pass in the nested inner list to it, instead of passing each individual key/value pair.
OLD POST:
Here is a clever little way to do this using reflection:
The basic idea:
Use a common base class for each Object class.
Put all of these classes in their own assembly.
Put this factory in that assembly too.
Pass in the KeyValuePair that you read from your config, and in return it finds the class that matches KV.Key and instantiates it with KV.Value
public class KeyValueToObjectFactory
{
private Dictionary _kvTypes = new Dictionary();
public KeyValueToObjectFactory()
{
// Preload the Types into a dictionary so we can look them up later
// Obviously, you want to reuse the factory to minimize overhead, so don't
// do something stupid like instantiate a new factory in a loop.
foreach (Type type in typeof(KeyValueToObjectFactory).Assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(KVObjectBase)))
{
_kvTypes[type.Name.ToLower()] = type;
}
}
}
public KVObjectBase CreateObjectFromKV(KeyValuePair kv)
{
if (kv != null)
{
string kvName = kv.Key;
// If the Type information is in our Dictionary, instantiate a new instance of that class.
Type kvType;
if (_kvTypes.TryGetValue(kvName, out kvType))
{
return (KVObjectBase)Activator.CreateInstance(kvType, kv.Value);
}
else
{
throw new ArgumentException("Unrecognized KV Pair");
}
}
else
{
return null;
}
}
}
#David:
I already have the parser (and most of these will be hand written, so I decided against XML). But that looks like I really nice way of doing it; I'll have to check it out. Excellent point about versioning too.
#Argelbargel:
That looks good too. :')
...This is a fairly core piece of the
project I'm working on though...
Is it really?
It's tempting to just abstract it and provide a basic implementation with the intention of refactoring later on.
Then you can get on with what matters: the game.
Just a thought
<bb />
Is it really?
Yes; I have thought this out. Far be it from me to do more work than neccessary. :')