I have read a lot about the danger of using structures as a data type, I wonder if there is any problem with this one,
List<Summarized> SummarizedList = new List<Summarized>();
Summarized SumInfo;
struct Summarized
{
public string sBrand;
public string sModel;
public string sCustomer;
public int sline;
public string sLeader;
public int sDesire;
public int sReal;
}
As you can see I use a generic list of items type SumInfo which is the struct data type. whenever I need to update an item of the list I just do the following:
SumInfo = (Summarized)SummarizedList[CurrentPos];
SumInfo.sDesire = DesireProd;
SumInfo.sReal = RealProduced;
SummarizedList[CurrentPos] = SumInfo;
where CurrentPos is the position of the item I want to update.
Everything works fine so far, so could be any problem with that in the future? Is this struct one of the mutable ones?
Thanks.
Everything works fine so far, so could be any problem with that in the future? Is this struct one of the mutable ones?
Yes, it's a mutable struct. Yes, it will work.
However, I would argue that this struct should be a class. For details as to why, refer to Choosing Between Classes and Structures. In this case, you're violating 3 of the cases which should always be true for structs:
It logically represents a single value, similar to primitive types (integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
This would strongly suggest a class is more appropriate for your type. It would also simplify your code.
BTW - Side note, the cast is not required in your code above. You should be able to just write:
SumInfo = SummarizedList[CurrentPos];
Issues:
It's a mutable struct, and they're almost always a bad idea (search for "mutable structs evil" and you'll get loads of hits)
It's got public fields - therefore no encapsulation; no separation between the API of the type an its implementation
It's got public members which don't follow the normal .NET naming conventions
It doesn't logically represent a single value, as per the .NET design guidelines
It's larger than the 16 bytes recommended by the same guidelines (although I wouldn't pay too much attention to that if everything else were okay)
Basically it's a dumb data bucket. There's a time and place for that, but it should almost always be a class in that case, and I'd personally usually try to make it an immutable type as well.
is there any reason you're using a struct? if you made it a class, the List would just contain references, and your code would look like:
SumInfo = SummarizedList[CurrentPos];
SumInfo.sDesire = DesireProd;
SumInfo.sReal = RealProduced;
// you're done! no need to insert it back in, you're referring to the same item
Personally, I would have nothing against using this struct. It may depend more on how you use it, whether you encapsulate the List methods etc.
The mutability of it depends on whether you are expecting to update any antries once you have added them to the list. If you are not expecting to, then your STRUCT is immutable, but your list isn't. However in this case you are updating the entries, so it is.
I would concur that a class is probably a better option for this.
Issue 1:
Yes the struct is mutable. And it suffers from all the problems associated with that.
SummarizedList[CurrentPos].sDesire=DesireProd;
shows why using a mutable struct like this is a bad idea, since it will not change the struct in the list.
Issue 2:
You have public mutable fields. This is considered bad style and you should use properties instead.
Issue 3:
You're using (System) Hungarian notation. When developing in C# follow the .net naming conventions.
Related
I have a struct which I put in a List<T>, I want to edit some value in that struct at a specific position. Is this at all possible without making a copy of the struct, editing the copy, and replacing the entry in the List?
No, to be able to do it you need reference to element of inner array which is not provided by List/IList.
You can do that with unsafe code and arrays if you have to.
From J.Richter's "CLR via C#", 3rd edition:
Value types should be immutable: that is, they should not define any
members that modify any of the type’s instance fields. In fact, I
recommended that value types have their fields marked as readonly so
that the compiler will issue errors should you accidentally write a
method that attempts to modify a field.
...
Just keep in mind that value types and reference types have very
different behaviors depending on how they’re used.
Consider this code:
public interface IChangeStruct
{
int Value { get; }
void Change(int value);
}
public struct MyStruct : IChangeStruct
{
int value;
public MyStruct(int _value)
{
value = _value;
}
public int Value
{
get
{
return value;
}
}
public void Change(int value)
{
this.value = value;
}
}
and it's usage:
static void Main(string[] args)
{
MyStruct[] l = new MyStruct[]
{
new MyStruct(0)
};
Console.WriteLine(l[0].Value);
l[0].Change(10);
Console.WriteLine(l[0].Value);
Console.ReadLine();
}
The output is:
0
10
So it does what you need.
However the same won't work for List<T>. I guess by the reason, mentioned by Alexei Levenkov. So, I would strongly recommend you to change struct to class if the type in question is not immutable per instance.
Your best bet is probably to have your structures expose their fields directly, and then use code like:
var temp = myList[3];
temp.X += 4;
myList[3] = temp;
I consider the failure of .net to provide any means of updating list items in place to be a significant weakness in .net, but would still consider an exposed-field struct as being far superior to any alternative in cases where one wishes to represent a small group of orthogonal values which should not be "attached" to any other such group (such as the coordinates in a point, the origin and size of a rectangle, etc.) The notion that structs should be "immutable" has been repeated as mantra for a long time, but that doesn't mean it's good advice. Such notion stems largely from two things:
Structs which modify `this` in any members outside their constructors are quirky. Such quirks used to (and to some extent still do) apply to property setters, but not to structs which simply expose their fields directly. Because Microsoft wrapped all struct fields in properties, this meant that while mutable structures could have had sensible semantics if they'd had exposed fields, they ended up with quirky semantics; Microsoft then blamed the quirky semantics on the fact that structs were mutable, rather than on the needless wrapping of fields with properties.
Some people like to model .net has only having one kind of object, as opposed to having value types and reference types as distinct kinds of entities. The behavior of so-called "immutable" value types is close enough to that of reference types that they can pretend they're the same thing, whereas the behavior of easily-mutable value types is vastly different. In reality, it's easier to understand the behavior of exposed-field value types than to understand all the corner cases where so-called "immutable" value types behave differently from reference types, and understanding the latter is impossible without understanding the former. Note that while value types may pretend to be immutable, there is in reality no such thing as an immutable value type. The only distinction is between those which can be mutated conveniently and those which can only be mutated awkwardly.
In reality, if a type is supposed to represent a small group of orthogonal values, an exposed-field struct is a perfect fit. Even if one has to use clunky code like that shown above to update a field of an item in a List<structType>, it's better than any alternative using class types or so-called "immutable" structs. Knowing that myList is a structure with an exposed field X would be enough to completely understand the code above. The only remotely decent alternative if one were using a class or "immutable" struct would be myList[3] = myList[3].WithX(myList[3].X + 4);, but that would require that the type in question to offer a WithX method (and presumably a WithWhatever() method for each field). Such methods would increase many fold the amount of code one would have to read to find out for certain what a method would actually do (one might expect that WithX would return a new instance which was identical to the old one except for the value of X, but one wouldn't know until one read all the code involved; by contrast, knowing that X is an exposed field of the structure type would be sufficient to know what the above code would do.
I've been writing C# for seven years now, and I keep wondering, why do enums have to be of an integral type? Wouldn't it be nice to do something like:
enum ErrorMessage
{
NotFound: "Could not find",
BadRequest: "Malformed request"
}
Is this a language design choice, or are there fundamental incompatibilities on a compiler, CLR, or IL level?
Do other languages have enums with string or complex (i.e. object) types? What languages?
(I'm aware of workarounds; my question is, why are they needed?)
EDIT: "workarounds" = attributes or static classes with consts :)
The purpose of an Enum is to give more meaningful values to integers. You're looking for something else besides an Enum. Enums are compatible with older windows APIs and COM stuff, and a long history on other platforms besides.
Maybe you'd be satisfied with public const members of a struct or a class.
Or maybe you're trying to restrict some specialized types values to only certain string values? But how it's stored and how it's displayed can be two different things - why use more space than necessary to store a value?
And if you want to have something like that readable in some persisted format, just make a utility or Extension method to spit it out.
This response is a little messy because there are just so many reasons. Comparing two strings for validity is much more expensive than comparing two integers. Comparing literal strings to known enums for static type-checking would be kinda unreasonable. Localization would be ... weird. Compatibility with would be broken. Enums as flags would be meaningless/broken.
It's an Enum. That's what Enums do! They're integral!
Perhaps use the description attribute from System.ComponentModel and write a helper function to retrieve the associated string from an enum value? (I've seen this in a codebase I work with and seemed like a perfectly reasonable alternative)
enum ErrorMessage
{
[Description("Could not find")]
NotFound,
[Description("Malformed request")]
BadRequest
}
What are the advantages, because I can only see drawbacks:
ToString will return a different string to the name of the enumeration. That is, ErrorMessage.NotFound.ToString() will be "Could not find" instead of "NotFound".
Conversely, with Enum.Parse, what would it do? Would it still accept the string name of the enumeration as it does for integer enumerations, or does it work with the string value?
You would not be able to implement [Flags] because what would ErrorMessage.NotFound | ErrorMessage.BadRequest equal in your example (I know that it doesn't really make sense in this particular case, and I suppose you could just say that [Flags] is not allowed on string-based enumerations but that still seems like a drawback to me)
While the comparison errMsg == ErrorMessage.NotFound could be implemented as a simple reference comparison, errMsg == "Could not find" would need to be implemented as a string comparison.
I can't think of any benefits, especially since it's so easy to build up your own dictionary mapping enumeration values to "custom" strings.
The real answer why: There's never been a compelling reason to make enums any more complicated than they are. If you need a simple closed list of values - they're it.
In .Net, enums were given the added benefit of internal representation <-> the string used to define them. This one little change adds some versioning downsides, but improves upon enums in C++.
The enum keyword is used to declare an
enumeration, a distinct type that
consists of a set of named constants
called the enumerator list.
Ref: msdn
Your question is with the chosen storage mechanism, an integer. This is just an implementation detail. We only get to peek beneath the covers of this simple type in order to maintain binary compatibility. Enums would otherwise have very limited usefulness.
Q: So why do enums use integer storage? As others have pointed out:
Integers are quick and easy to compare.
Integers are quick and easy to combine (bitwise for [Flags] style enums)
With integers, it's trivially easy to implement enums.
* none of these are specific to .net, and it appears the CLR designers apparently didn't feel compelled to change anything or add any gold plating to them.
Now that's not to saying your syntax isn't entirely unappealing. But is the effort to implement this feature in the CLR, and all the compilers, justified? For all the work that goes into this, has it really bought you anything you couldn't already achieve (with classes)? My gut feeling is no, there's no real benefit. (There's a post by Eric Lippert I wanted to link to, but I couldn't find it)
You can write 10 lines of code to implement in user-space what you're trying to achieve without all the headache of changing a compiler. Your user-space code is easily maintained over time - although perhaps not quite as pretty as if it's built-in, but at the end of the day it's the same thing. You can even get fancy with a T4 code generation template if you need to maintain many of your custom enum-esque values in your project.
So, enums are as complicated as they need to be.
Not really answering your question but presenting alternatives to string enums.
public struct ErrorMessage
{
public const string NotFound="Could not find";
public const string BadRequest="Malformed request";
}
Perhaps because then this wouldn't make sense:
enum ErrorMessage: string
{
NotFound,
BadRequest
}
It's a language decision - eg., Java's enum doesn't directly correspond to an int, but is instead an actual class. There's a lot of nice tricks that an int enum gives you - you can bitwise them for flags, iterate them (by adding or subtracting 1), etc. But, there's some downsides to it as well - the lack of additional metadata, casting any int to an invalid value, etc.
I think the decision was probably made, as with most design decisions, because int enums are "good enough". If you need something more complex, a class is cheap and easy enough to build.
Static readonly members give you the effect of complex enums, but don't incur the overhead unless you need it.
static class ErrorMessage {
public string Description { get; private set; }
public int Ordinal { get; private set; }
private ComplexEnum() { }
public static readonly NotFound = new ErrorMessage() {
Ordinal = 0, Description = "Could not find"
};
public static readonly BadRequest = new ErrorMessage() {
Ordinal = 1, Description = "Malformed Request"
};
}
Strictly speaking, the intrinsic representation of an enum shouldn't matter, because by definition, they are enumerated types. What this means is that
public enum PrimaryColor { Red, Blue, Yellow }
represents a set of values.
Firstly, some sets are smaller, whereas other sets are larger. Therefore, the .NET CLR allows one to base an enum on an integral type, so that the domain size for enumerated values can be increased or decreased, i.e., if an enum was based on a byte, then that enum cannot contain more than 256 distinct values, whereas one based on a long can contain 2^64 distinct values. This is enabled by the fact that a long is 8 times larger than a byte.
Secondly, an added benefit of restricting the base type of enums to integral values is that one can perform bitwise operations on enum values, as well as create bitmaps of them to represent more than one values.
Finally, integral types are the most efficient data types available inside a computer, therefore, there is a performance advantage when it comes to comparing different enum values.
For the most part, I would say representing enums by integral types seems to be a CLR and/or CLS design choice, though one that is probably not very difficult to arrive at.
The main advantage of integral enums is that they don't take up much space in memory. An instance of a default System.Int32-backed enum takes up just 4-bytes of memory and can be compared quickly to other instances of that enum.
In constrast, string-backed enums would be reference types that require each instance to be allocated on the heap and comparisons to involve checking each character in a string. You could probably minimize some of the issues with some creativity in the runtime and with compilers, but you'd still run into similar problems when trying to store the enum efficiently in a database or other external store.
While it also counts as an "alternative", you can still do better than just a bunch of consts:
struct ErrorMessage
{
public static readonly ErrorMessage NotFound =
new ErrorMessage("Could not find");
public static readonly ErrorMessage BadRequest =
new ErrorMessage("Bad request");
private string s;
private ErrorMessage(string s)
{
this.s = s;
}
public static explicit operator ErrorMessage(string s)
{
return new ErrorMessage(s);
}
public static explicit operator string(ErrorMessage em)
{
return em.s;
}
}
The only catch here is that, as any value type, this one has a default value, which will have s==null. But this isn't really different from Java enums, which themselves can be null (being reference types).
In general, Java-like advanced enums cross the line between actual enums, and syntactic sugar for a sealed class hierarchy. Whether such sugar is a good idea or not is arguable.
We have seen lots of discussion in SO regarding the class vs struct in c#. Mostly ended with conclusions saying its a heap/stack memory allocation. And recommending to use structs in small data structures.
Now I have a situation to decide the simple data store among these two choices. Currenlty in our application we have thousands of classes, just acts as simple data stores (only exposed public fields) and they passed among different modules and services.
As per my understanding, I felt it's better to move ahead with struct instead classes for the performance reasons. Because these are simple data structures only act as data stores.
Before proceeding with this, I need some expert advice from the people who have experienced this struggle.
is my understanding correct?
I have seen most ORMs have classes as data stores. So I doubt there should a reason to go ahead with classes instead structs. what would that be?
I would make the choice based on the following criteria
reference type vs value type semantics. If 2 objects are only equal if they are the same object, it indicates reference type semantics => class. If the value of its members defines equality (e.g. 2 DateTimes are equal if both represent the same point in time even if they are 2 distinct objects), value type semantics => struct
Memory footprint of the object. If the object is huge and frequently allocated, making it a struct would consume the stack much faster, hence I'd rather have it as a class. On the contrary, I'd rather avoid the GC penalty for small value types; hence make them a struct.
can you make the object immutable? I find structs great for 'value objects' - from the DDD book.
Would you face some boxing-unboxing penalty based on the usage of this object? If yes, go for class.
A pretty cool, not so well known advantage of Structs over Classes is that there is an automatic implementation of GetHashcode and Equals in structs.
That's pretty useful when keys are required for dictionaries
The struct implementation of GetHashcode and Equals is based on the binary content of the struct instances + reflection for the reference members (like String members and other instances of classes)
So the following code works for GethashCode/Equals :
public struct Person
{
public DateTime Birthday { get; set; }
public int Age{ get; set; }
public String Firstname { get; set; }
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
Person p2 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
Debug.Assert(p1.Equals(p2));
Debug.Assert(p1.GetHashCode() == p2.GetHashCode());
}
}
Both assertions succeed when Person is a struct
Both assertions fail if Person is a class instead of a struct
Reference :
https://msdn.microsoft.com/en-Us/library/2dts52z7%28v=vs.110%29.aspx
Regards, best coding
structs should be defined immutable where in classes should not. If you think your objects are going to be small and immutable you can go ahead with making them structs or else let them be classes.
I can never really seem to remember, exactly how structs are different, but they are. In subtle ways. In fact, sometimes they come and bite you.
So. Unless you know what you are doing, just stick to classes.
I know this sounds a little newbie. I know I should right now go and look up the differences and display them here - but that has already been done by others. All I'm saying is that adding a different type of objects creates a semantical burden, a bit of extra complexity that you are wise to consider carefully.
If I remember correctly, one of the biggest problem is the value semantics of structs: Passing them around will result in different objects (as they get passed by value). If you then change some field in one place, beware that in all other places the field did not get changed! That is why everyone is recommending immutability for structs!
EDIT: For the case you are describing, structs won't work!
A class object has the advantage that it's possible to pass around a reference to it, with the scope and lifetime of such a reference being unlimited if it reaches outside code. A struct has the advantage that while it's possible to pass around short-lived references to them, it's not possible to pass around perpetual promiscuous references. This helps avoid having to worry about whether such references exist.
Some people have suggested that data holders which are mutable should not be structs. I emphatically disagree. Entities which exists for the purpose of holding data should, in many cases, be structs, especially if they are mutable. Eric Lippert has posted many times that he considers mutable value types evil (search under tags "mutable" and "struct"). It is certainly true that .net allows certain things to be done with mutable structs which it shouldn't, and doesn't conveniently allow some things that it should, but POD ("Plain Old Data") structs which have no mutating methods, but instead expose their entire state via public fields, have a very useful consistency in their behavior which is not shared with any other data type. Using a POD struct may confuse someone who isn't familiar with how they work, but will make the program much more readable by anyone who does.
Consider, for example, the following code, assuming EmployeeInfoStruct contains nothing but value types and immutable class types like String:
[employeeInfoStruct is a struct containing the following field]
public Decimal YearlyBonus;
[someEmployeeContainer is an instance of a class which includes the following method]
EmployeeInfoStruct GetEmployeeInfo(String id); // Just the signature--code is immaterial
[some other method uses the following code]
EmployeeInfoStruct anEmployee = someEmployeeContainer.GetEmployeeInfo("123-45-6789");
anEmployee.YearlyBonus += 100;
Eric Lippert complains that the above code will alter the value in anEmployee, but that change won't have any effect on the container. I would suggest that's a good thing--anyone who knows how structs work could look at the above code and know writes to a struct variable will affect that variable, but won't affect anything else unless the program later uses some other method (perhaps SetEmployeeInfo) to store that variable someplace.
Now replace EmployeeInfoStruct with EmployeeInfoClass, which has a read/write property of type YearlyBonus. Using just the information above, what can one say about the the relationship between writes to someEmployeeContainer and anEmployee? Depending upon the implementations of anEmployee's class (which, unless EmployeeInfoClass is sealed, might or might not actually be EmployeeInfoClass) and someEmployeeContainer, the relationship between the objects could be anything. Writes to one might:
Have no effect on the other
Update the other in 'natural' fashion
Corrupt the other in some arbitrary way
With structs containing nothing but fields of either value types or immutable classes, the semantics are always going to be #1. One doesn't have to look at the code for the struct itself, nor the code of the container, to know that. By contrast, if the anEmployee.Salary or someEmployeeContainer.GetEmployee is virtual, it's impossible to really know what the semantics will be.
It's important to note that, if structs are large, passing them by value or returning them from functions can be expensive. It's generally better to pass large structs as ref parameters when possible. Although the built-in collections really don't do a good job of facilitating such usage, it can make using a hundreds-of-bytes struct cheaper than using a class.
The comment about structs being immutable is correct. And this is where it can bite you. You can define structs with field setters, but when you change a field value a new instance is created. So if you hold a reference to the old object it will still reference the old value. I don't like using mutable stucts for this reason as this can produce subtle and complex bugs (especially if you use complex compound statements).
On the other hand, there are lots of good reasons for using classes with immutable state also (think string).
I remember one advice given on MSDN that struct should not be larget than 16 or 21 bytes. Looking for the link, but can't find it yet.
The main implication was that once you have a string in your data type - make it a class without thinking. Otherwise the struct shouldn't hold much.
I think you have the right idea. Structs are made to mimic data-types. They are value driven not reference based. If you look at the MSDN documentation for most of the base data classes (int, double, decimal, ect.) they are all based on structs. That being said however, structs should not be overused for that very same reason. Room to store all everything in that struct is allocated as soon as it is instantiated, where as classes just allocate room for a reference to everything inside. If the data is in small enough chunks where this is not a problem than structs are the way to go. If this is an issue go with classes. If you don't know than it might just be best to stick with what you are familiar with.
If you have low latency requirements and A LOT of objects slow garbage collections can be a problem. In that case struct can be very helpful because the garbage collector does not need to scan through a hierarchy of value types if the value types does not contain any reference types.
You can find a benchmark here: http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/
In a recent project I was working I created a structure in my class to solve a problem I was having, as a colleague was looking over my shoulder he looked derisively at the structure and said "move it into a class".
I didn't have any argument for not moving it into a class other than I only need it in this class but this kind of falls down because couldn't I make it a nested class?
When is it ok to use a structure?
You should check out the value type usage guidelines: http://msdn.microsoft.com/en-us/library/y23b5415(vs.71).aspx
The article lists several important points but the few that I feel are the most valuable are the following
Is the value immutable?
Do you want the type to have value semantics?
If the answer to both questions is yes then you almost certainly want to use a Structure. Otherwise I would advise going with a class.
There are issues with using structures with a large amount of members. But I find that if I consider the two points above, rarely do I have more than the recommended number of members / size in my value types.
MSDN has a good guidelines document to cover structure usage. To summarize:
Act like primitive types.
Have an instance size under 16 bytes.
Are immutable.
Value semantics are desirable.
Otherwise, use a class.
You should always use a Class as your first choice, changing to Structure only for very specific reasons (as others have already outlined).
Depending on how much you "only need it in this class", you might be able to avoid the nested type completely by using an anonymous type; this will only work within a single method:
Public Class Foo
Public Sub Bar
Dim baz = New With { .Str = "String", .I = 314 }
End Sub
End Class
you can't (readily--there are a few things you can do with generics) move the instance baz outside of the Sub in a typesafe manner. Of course an Object can hold anything, even an instance of an anonymous type.
I think structures are great if you need copy the object or do not want it to be modified by the passed function. Since passed functions can not modify the originally passed structure instead got a new copy of it, this can be a life saver. (unless they passed as ByRef obviously) and can save you trouble of deep copy craziness in .NET or implementing pain of an ICloneSomething implementation.
But the general idea is defining a custom data structure in a more semantic way.
About moving to a class, if you are moving into a class where it'll be part of a class, generally this is good practice since your structure is 99% of the time related with one of you classes not related with a namespace.
If you are converting it to a class then you need to consider "is it defining a data strcuture" and "is it expensive?" since it's gonna be copied all over the place, "do you want to get affected by modifications done by the passers?"
The usage guidelines referenced by Marc and Rex are excellent and nicely cover cases where you aren't sure which one you would want. I will list some use cases where use of a struct is a requirement.
When you need to set the layout of the fields in memory
Interop with unmanaged code.
When you want to make Unions.
You need a fixed size buffer inlined.
You want to be able to do the equivalent of a reinterpret_cast with relative safety (so long as the struct does not contain any fields which are themselves reference types.
These are normally edge cases and (with the exception of interop) not recommended practices unless their use is necessary for the success of the project/program.
I'm just wondering how other developers tackle this issue of getting 2 or 3 answers from a method.
1) return a object[]
2) return a custom class
3) use an out or ref keyword on multiple variables
4) write or borrow (F#) a simple Tuple<> generic class
http://slideguitarist.blogspot.com/2008/02/whats-f-tuple.html
I'm working on some code now that does data refreshes. From the method that does the refresh I would like to pass back (1) Refresh Start Time and (2) Refresh End Time.
At a later date I may want to pass back a third value.
Thoughts? Any good practices from open source .NET projects on this topic?
It entirely depends on what the results are. If they are related to one another, I'd usually create a custom class.
If they're not really related, I'd either use an out parameter or split the method up. If a method wants to return three unrelated items, it's probably doing too much. The exception to this is when you're talking across a web-service boundary or something else where a "purer" API may be too chatty.
For two, usually 4)
More than that, 2)
Your question points to the possibility that you'll be returning more data in the future, so I would recommend implementing your own class to contain the data.
What this means is that your method signature will remain the same even if the inner representation of the object you're passing around changes to accommodate more data. It's also good practice for readability and encapsulation reasons.
Code Architeture wise i'd always go with a Custom Class when needing somewhat a specific amount of variables changed. Why? Simply because a Class is actually a "blueprint" of an often used data type, creating your own data type, which it in this case is, will help you getting a good structure and helping others programme for your interface.
Personally, I hate out/ref params, so I'd rather not use that approach. Also, most of the time, if you need to return more than one result, you are probably doing something wrong.
If it really is unavoidable, you will probably be happiest in the long run writing a custom class. Returning an array is tempting as it is easy and effective in the short teerm, but using a class gives you the option of changing the return type in the future without having to worry to much about causing problems down stream. Imagine the potential for a debugging nightmare if someone swaps the order of two elements in the array that is returned....
I use out if it's only 1 or 2 additional variables (for example, a function returns a bool that is the actual important result, but also a long as an out parameter to return how long the function ran, for logging purposes).
For anything more complicated, i usually create a custom struct/class.
I think the most common way a C# programmer would do this would be to wrap the items you want to return in a separate class. This would provide you with the most flexibility going forward, IMHO.
It depends. For an internal only API, I'll usually choose the easiest option. Generally that's out.
For a public API, a custom class usually makes more sense - but if it's something fairly primitive, or the natural result of the function is a boolean (like *.TryParse) I'll stick with an out param. You can do a custom class with an implicit cast to bool as well, but that's usually just weird.
For your particular situation, a simple immutable DateRange class seems most appropriate to me. You can easily add that new value without disturbing existing users.
If you're wanting to send back the refresh start and end times, that suggests a possible class or struct, perhaps called DataRefreshResults. If your possible third value is also related to the refresh, then it could be added. Remember, a struct is always passed by value, so it's allocated on the heap does not need to be garbage-collected.
Some people use KeyValuePair for two values. It's not great though because it just labels the two things as Key and Value. Not very descriptive. Also it would seriously benefit from having this added:
public static class KeyValuePair
{
public static KeyValuePair<K, V> Make(K k, V v)
{
return new KeyValuePair<K, V>(k, v);
}
}
Saves you from having to specify the types when you create one. Generic methods can infer types, generic class constructors can't.
For your scenario you may want to define generic Range{T} class (with checks for the range validity).
If method is private, then I usually use tuples from my helper library. Public or protected methods generally always deserve separate.
Return a custom type, but don't use a class, use a struct - no memory allocation/garbage collection overhead means no downsides.
If 2, a Pair.
If more than 2 a class.
Another solution is to return a dictionary of named object references. To me, this is pretty equivalent to using a custom return class, but without the clutter. (And using RTTI and reflection it is just as typesafe as any other solution, albeit dynamically so.)
It depends on the type and meaning of the results, as well as whether the method is private or not.
For private methods, I usually just use a Tuple, from my class library.
For public/protected/internal methods (ie. not private), I use either out parameter or a custom class.
For instance, if I'm implementing the TryXYZ pattern, where you have an XYZ method that throws an exception on failure and a TryXYZ method that returns Boolean, TryXYZ will use an out parameter.
If the results are sequence-oriented (ie. return 3 customers that should be processed) then I will typically return some kind of collection.
Other than that I usually just use a custom class.
If a method outputs two to three related value, I would group them in a type. If the values are unrelated, the method is most likely doing way too much and I would refactor it into a number of simpler methods.