This question already has answers here:
Why don't structs support inheritance?
(10 answers)
Closed 9 years ago.
I am reading CLR via C# by Jeffery Richter and it says a struct is a value type and cannot be inherited.
Are there any technical or philosophical reasons?
ADD 1 - 5:53 PM 11/11/2020
Every decision, no matter how reasonable or accidental it may look, has its impact, subtle or profound. We try to decouple things, sometimes by creating new coupling...
Edit: There are serious editorial concerns about this post, apparently. See comment section.
A little of both.
Philosophically, it works out - there are classes, which are the "real" building block for object oriented programming, and there are structs, which are lightweight data types for storage but allow object-like method calls for familiarity and convenience.
Technically, being a "value type" means that the entire struct - all of its contents - are (usually) stored wherever you have a variable or member of that type. As a local variable or function parameter, that means on the stack. For member variables, that means stored entirely as part of the object.
As a (primary) example of why inheritance is a problem, consider how storage is affected at a low level if you allowed structs to have subtypes with more members. Anything storing that struct type would take up a variable amount of memory based on which subtype it ended up containing, which would be an allocation nightmare. An object of a given class would no longer have a constant, known size at compile time and the same would be true for stack frames of any method call. This does not happen for objects, which have storage allocated on the heap and instead have constant-sized references to that storage on the stack or inside other objects.
This is just an intuitive, high-level explanation - See comments and other answers for both expanded and more precise information.
Edit: The link in the comments to Eric Lippert's article The Stack Is An Implementation Detail, is now located on his personal blog site.
Because it is the way structs are represented in .NET. They are value types and value types don't have a method table pointer allowing inheritance.
You may find the answers to SO Question Why are .NET value types sealed? relevant. In it, #logicnp refers to ECMA 335, which states:
8.9.10 Value type inheritance
[...]
Will be sealed to avoid dealing with the complications of value slicing.
The more restrictive rules specified here allow for more efficient implementation without severely compromising functionality.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
It seems like a good design decision that the System.Object class, and hence all classes, in .NET provide a ToString() method which, unsurprisingly, returns a string representation of the object. Additionally in C# this method is implemented for native types so that they integrate nicely with the type system.
This often comes in handy when user interaction is required. For example, objects can directly be held in GUI widgets like lists and are "automatically" displayed as text.
What is the rationale in the language design to not provide a similarly general object.FromString(string) method?
Other questions and their answers discuss possible objections, but I find them not convincing.
The parse could fail, while a conversion to string is always possible.
Well, that does not keep Parse() methods from existing, does it? If exception handling is considered an undesirable design, one could still define a TryParse() method whose standard implementation for System.Object simply returns false, but which is overridden for concrete types where it makes sense (e.g. the types where this method exists today anyway).
Alternatively, at a minimum it would be nice to have an IParseable interface which declares a ParseMe() or TryParse() method, along the lines of ICloneable.
Comment by Tim Schmelter's "Roll your own": That works of course. But I cannot write general code for native types or, say, IPAddress if I must parse the values; instead I have to resort to type introspection or write wrappers which implement a self-defined interface, which is either maintenance-unfriendly or tedious and error-prone.
Comment by Damien: An interface can only declare non-static functions for reasons discussed here by Eric Lippert. This is a very valid objection. A static TryParse() method cannot be specified in an interface. A virtual ParseMe(string) method though needs a dummy object, which is a kludge at best and impossible at worst (with RAII). I almost suspect that this is the main reason such an interface doesn't exist. Instead there is the elaborate type conversion framework, one of the alternatives mentioned as solutions to the "static interface" oxymoron.
But even given the objections listed, the absence of a general parsing facility in the type system or language appears to me as an awkward asymmetry, given that a general ToString() method exists and is extremely useful.
Was that ever discussed during language/CLR design?
It seems like a good design decision that the System.object class, and hence all classes, in .NET provide a ToString() method
Maybe to you. It's always seemed like a really bad idea to me.
which, unsurprisingly, returns a string representation of the object.
Does it though? For the vast majority of types, ToString returns the name of the type. How is that a string representation of the object?
No, ToString was a bad design in the first place. It has no clear contract. There's no clear guidance on what its semantics should be, aside from having no side effects and producing a string.
Since ToString has no clear contract, there is practically nothing you can safely use it for except for debugger output. I mean really, think about it: when was the last time you called ToString on object in production code? I never have.
The better design therefore would have been methods static string ToString<T>(T) and static string ToString(object) on the Debug class. Those could have then produced "null" if the object is null, or done some reflection on T to determine if there is a debugger visualizer for that object, and so on.
So now let's consider the merits of your actual proposal, which is a general requirement that all objects be deserializable from string. Note that first, obviously this is not the inverse operation of ToString. The vast majority of implementations of ToString do not produce anything that you could use even in theory to reconstitute the object.
So is your proposal that ToString and FromString be inverses? That then requires that every object not just be "represented" as a string, but that it actually be round trip serializable to string.
Let's think of an example. I have an object representing a database table. Does ToString on that table now serialize the entire contents of the table? Does FromString deserialize it? Suppose the object is actually a wrapper around a connection that fetches the table on demand; what do we serialize and deserialize then? If the connection needs my password, does it put my password into the string?
Suppose I have an object that refers to another object, such that I cannot deserialize the first object without also having the second in hand. Is serialization recursive across objects? What about objects where the graph of references contains loops; how do we deal with those?
Serialization is difficult, and that's why there are entire libraries devoted to it. Making it a requirement that all types be serializable and deserializable is onerous.
Even supposing that we wanted to do so, why string of all things? Strings are a terrible serialization data type. They can't easily hold binary data, they have to be entirely present in memory at once, they can't be more than a billion characters tops, they have no structure to them, and so on. What you really want for serialization is a structured binary storage system.
But even given the objections listed, the absence of a general parsing facility in the type system or language appears to me as an awkward asymmetry, given that a general ToString() method exists and is extremely useful.
Those are two completely different things that have nothing to do with each other. One is a super hard problem best solved by libraries devoted to it, and the other is a trivial little debugging aid with no specification constraining its output.
Was that ever discussed during language/CLR design?
Was ToString ever discussed? Obviously it was; it got implemented. Was a generalized serialization library ever discussed? Obviously it was; it got implemented. I'm not sure what you're getting at here.
Why is there no inverse to object.ToString()?
Because object should hold the bare minimum functionality required by every object. Comparing equality and converting to string (for a lot of reasons) are two of them. Converting isn't. The problem is: how should it convert? Using JSON? Binary? XML? Something else? There isn't one uniform way to convert from a string. Hence, this would unnecessarily bloat the object class.
Alternatively, at a minimum it would be nice to have an IParseable interface
There is: IXmlSerializable for example, or one of the many alternatives.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I've been reading a book on C# and it explains that int, float, double etc. are "basic" types meaning that they store the information at the lowest level of the language, while a type such as 'object' puts information in the memory and then the program has to access this information there. I don't know exactly what this means as a beginner, though!
The book however does not explain what the difference is. Why would I use int or string or whatever instead of just object every time, as object is essentially any of these types?
How does it impact the performance of the program?
This is a very broad subject, and I'm afraid your question as currently stated is prone to being put on hold as such. This answer will barely scratch the surface. Try to educate yourself more, and then you'll be able to ask a more specific question.
Why would I use int or string or whatever instead of just object every time, as object is essentially any of these types?
Basically you use the appropriate types to store different types of information in order to execute useful operations on them.
Just as you don't "add" two objects, you can't get the substring of a number.
So:
int foo = 42;
int bar = 21;
int fooBar = foo + bar;
This won't work if you declared the variables as object. You can do an addition because the numeric types have mathematical operators defined on them, such as the + operator.
You can refer to an integer type as an object (or any type really, as in C# everything inherits from object):
object foo = 42;
However now you won't be able to add this foo to another number. It is said to be a boxed value type.
Where exactly these different types are stored is a different subject altoghether, about which a lot has been written already. See for example Why are Value Types created on the Stack and Reference Types created on the Heap?. Also relevant is the difference between value types and reference types, as pointed out in the comments.
C# is a strongly typed language, which means that the compiler checks that the types of the variables and methods that you use are always consistent. This is what prevents you from writing things like this:
void PrintOrder(Order order)
{
...
}
PrintOrder("Hello world");
because it would make no sense.
If you just use object everywhere, the compiler can't check anything. And anyway, it wouldn't let you access the members of the actual type, because it doesn't know that they exist. For instance, this works:
OrderPrinter printer = new OrderPrinter();
printer.PrintOrder(myOrder);
But this doesn't
object printer = new OrderPrinter();
printer.PrintOrder(myOrder);
because there is no PrintOrder method defined in the class Object.
This can seem constraining if you come from a loosely-typed language, but you'll come to appreciate it, because it lets you detect lots of potential errors at compile time, rather than at runtime.
What the book is referring to is basically the difference between value types (int, float, struct, etc) and reference types (string, object, etc).
Value types store the content in a memory allocated on the stack which is efficient where as reference types (almost anything that can have the null value) store the address where data is. Reference types are allocated on the heap which is less efficient than the stack because there is a cost to allocating and deallocating the memory used to store your data. (and it's only deallocated by the garbage collector)
So if you are using object every time it will be slower to allocate the memory and slower to reclaim it.
Documentation
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I would like to know if there is a specific reason because of which C# doesn't have automatically generated Equals, GetHashCode, and operator ==, operator != geared towards value comparison in reference types.
*Explanation:
I do not see an easy way to quickly request "compare actual objects" operation for values/contents of reference types. Coming from C++ background I have impression that it is something that should be done automatically by compiler at simple request of user.
The lack of that feature most likely indicates that it might be against language's "design goal"/"vision"/"philosophy". So I would like to know for which reason this functionality was deemed to be unimportant.
--original text--
As far as I can tell, Equals pretty much amounts to few comparisons to null, attempted cast and field-by-field comparison.
GetHashCode pretty much amounts to combination of all hashes for members using some operations (multiply with overflow, xor, anything).
As far as I can tell, it should either automated: the methods should be generated by default OR there should be a simple way to request default implementation. However, there is no such thing. Why?
As I understand it, it is either massive technical oversight that persisted for years, or some kind of language philosophy I'm not aware of.
So, what is the reason?
In order for a compiler/framework to usefully auto-generate equivalence-related methods, it would need to be able to distinguish two kinds of equivalence and multiple kinds of reference. For example, suppose Foo has a single field of type int[], and two instances of Foo hold references to different arrays holding the sequence {1,2,3}. Whether or not a comparison between references to those instances should report them equal would depend upon the purpose for which Foo holds the array reference and the purpose for which the references to Foo objects are held by the code requesting the comparison.
If neither array's contents will ever be altered, the two Foo instances should report each other as being permanently equivalent (and also presently equivalent); if the arrays can be modified, but only at the request of code holding references to the Foo instances, then the instances should report themselves as being presently equivalent, but not permanently equivalent [if code which holds the only reference to a Foo instance and never shares it or calls any of its mutating methods, then it can know that the state of that instance will never change even if that instance doesn't know that]. If references to the arrays are in the hands of outside code that might modify them, then the instances are not equivalent even though the arrays presently hold the same value.
Since the type system has no way of knowing how what kind of comparison to do on int[] fields, there's no way it can generate a semantically-meaningful equality override.
For value types, Equals and GetHashCode are implemented for you automatically (though the implementation uses reflection, so it's faster to write your own).
And for reference types, it's not clear whether you want to compare the contents or compare the references. I've used both. If I'm writing an immutable type, I probably want its Equals to compare its contents. For anything else, I probably want the default Equals implementation that only returns true if I compare an instance to itself (reference equality); comparing contents would be the wrong thing in this case.
So, for value types (which are defined by their contents), .NET gives you what you want (but not as performant as what you could write yourself). For reference types, you have to opt into content equality, since often that wouldn't be what you want.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am currently learning C# and I have a situation where I have a class that contains a ISet. I don't wish clients to modify this set directly, and most clients only Add and Remove, and I provide accessors through my class to do this.
However, I have one client that wishes to know more about this set and its contents. I don't really want to muddy the wrapper class itself with lots of methods for this one client, so I would prefer to be able to return the set itself in a immutable way.
I found I can't - well, not really. The only options I seem to have are:
Return an IEnumerable (No: restrictive functionality);
ReadOnlyCollection (No: It's a LIST);
Return a copy (No: Bad form IMHO, allows clients to modify the returned collection perhaps unaware that it's not going to change the real object, plus it has performance overhead);
Implement my own ReadOnlySet (No: Would need to derive from ISet and thus meaning I need to implement mutators, probably firing exceptions, I would rather compile time errors - not runtime).
Am I missing something? Am I being unreasonable? Is my only option to provide the full set of accessors on my wrapper? Am I incorrect in my original intent to keep the wrapper clean for the vast majority of clients?
So two questions:
Why isn't there an standard C# immutable Collection interface? It seems like a fairly reasonable requirement?
Why is ReadOnlyCollection annoyingly called ReadOnlyCollection when it is really a ReadOnlyList? I was going to bite the bullet and use that until I found out it was a List (and I use a Set).
Why isn't there a standard C# immutable interface? It seems like a
fairly reasonable requirement?
A standard C# immutable¹ interface already exists: it's called IEnumerable and all containers implement it.
More powerful immutable interfaces are problematic, because there are many kinds of immutability. If the BCL team decided to pick one definition of immutability and elevate it to the immutability status it's certain that down the road people looking for a different kind of immutability would complain about the choice.
Satisfying everyone would mean not only sorting all of the immutability mess out but creating lots of interfaces (good luck picking good names for them too) and baking all these immutability concepts into the language well enough to make immutability a first-class citizen -- remember that there are no second chances here, once you ship a public class its public interface is immutable forever (pun intended). While all of this might be good to have, I 'm really skeptical about the cost/benefit ratio.
It's not difficult to define IReadOnlyList, IReadOnlySet and such if you do require them. I assume that they do not already exist because again, minus 100 points.
ReadOnlyCollection is IMHO either a concession or a class that was required internally for the BCL and exposed to the world because hey, free functionality at really low cost for the BCL team (since it would have to be implemented, documented and tested anyway). In any case I don't think that it does not live in the glamorous System.Collections.Generic neighborhood by chance.
Why is ReadOnlyCollection annoyingly called ReadOnlyCollection when it
is really a ReadOnlyList? I was going to bite the bullet and use that
until I found out it was a List (and I use a Set).
I 'm sure the BCL team would love to be able to go back in time and fix that, because it's almost certainly one of those little inconsistencies that unavoidably sneak into any library of comparable scope. Since ReadOnlyCollection implements IList it should definitely have been called ReadOnlyList.
However, given that a "list" offers more functionality than a "collection", I don't see how this would stop you. Neither is a Set, so you would have to build set-related functionality on top of them in any case (which is not a good idea; just build read-only semantics on top of Set).
¹ We 're tossing around "immutable" a lot here, but that word does not have a singular meaning. I think it would be more appropriate to use "read-only", but I 'll go with your choice of word for consistency.
This may help,
http://blogs.msdn.com/b/jaredpar/archive/2008/04/22/api-design-readonlycollection-t.aspx
I think the only way for you to provide a read-only 'copy' of the set without actually copying the data into another instance of the same or a different structure, is to go with the wrapper and implement all the item-adding-and-removing methods to throw an exception.
If your set is exposed only as an ISet anyway, consumers are only going to see the members defined on the interface, no matter what your wrapper contains - that doesn't seem like it's a bad thing.
I agree it would be nice if there were better support in .net for both immutability and read-only wrappers, though I think it's important to note that there is a huge difference between the concepts. A read-only wrapper promises its creator that consumers of it won't be able to change the underlying object, but makes no promise to consumers that the underlying object itself won't change. By contrast, an immutable object promises its creator and consumers that its values won't change.
I'm not sure why the notion that there are many different types of immunity should be a problem. If I have a generic ImmutableList<T> which takes an unqualified T my expectation would be that it will always contain the same T's as it did when it was created. The collection could in no way affect whether any of the properties of the T's could change, and thus it shouldn't be expected to.
If I had my druthers, most of the collection-related interfaces would include readable, mutable, and immutable variants (mutable and immutable would both extend from readable). I'd also add a write-only contravariant IAppendable interface, as well as an IImmutableEnumerable derived from IEnumerable (I'd add a ToImmutable method to IEnumerable (and IImmutableEnumerable); an implementation could construct an immutable collection, but in some cases that might not be the best approach. For example, a mutable object might implement IEnumerable by return a mutable number of copies of a mutable element. If the number of copies is large, converting to a simple collection could be very wasteful.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Why is the default decision in C++, C#, and Ada 95 to use static method binding, rather than dynamic method binding.?
Is the gain in implementation speed worth the loss in abstraction and re-usability?
In general, you can consider that you have todesign the base class for extensibility. If a member function (to use the C++ vocabulary) isn't designed to be overridden, there is a good chance than overriding it will in practice not be possible and for sure it won't it be possible without knowledge of what the class designer think is implementation details and will change without giving you prior notice.
Some additional considerations for two languages (I don't know C# enough to write about it):
Ada 95 would have had compatibility issues with Ada 83 if the choice was different. And considering the whole object model of Ada 95, doing it differently would have make no sense (but you can consider that compatibility was a factor in the choice of the object model).
For C++, performance was certainly a factor. The you don't pay for what you don't use principle and the possibility to use C++ just as a better C was quite instrumental in its success.
The obvious answer is because most functions shouldn't be virtual. As AProgrammer points out, unless a function has been designed explicitly to be overridden, you probably can't override it (virtual or not) without breaking class invariants. (When I work in Java, for example, I end up declaring most functions final, as a matter of good engineering. C++ and Ada make the right decision: the author must explicitly state that the function is designed to be overridden.
Also, C++ and (I think) Ada support value semantics. And value semantics doesn't work well with polymorphism; in Java, classes like java.lang.String are final, in order to simulate value semantics for them. Far to many applications programmers, however, don't bother, since it's not the default. (In a similar manner, far too many C++ programmers omit to inhibit copy and assignment when the class is polymorphic.)
Finally, even when a class is polymorphic, and designed for inheritance, the contract is still specified, and in so far as is reasonable, enforced, in the base class. In C++, typically, this means that public functions are not virtual, since it is the public functions which define and enforce the contract.
I can't speak about Ada, but for C++ two important goals for the design of C++ were:
backwards compatibility with C
you should pay nothing (to the extent possible) for features that you don't use
While neither of these would necessarily dictate that dynamic binding couldn't have been chosen to be the default, having static method binding (I assume you mean non-virtual member functions) does seem to 'fit' better with these design goals.
I'll give one of the other two thirds of Michael Burr's answer.
For Ada it was an important design goal that the language be suitable for system's programming and use on small realtime embedded devices (eg: missile and bomb CPUs). Perhaps there are now techniques that would allow dynamic languages to do such things well, but there certianly weren't back in the late 70's and early 80's when the language was first being designed. Ada95 of course could not radically deviate from the orginal language's basic underlying design, any more than C++ could from C.
That being said, both Ada and C++ (and certianly C# as well?) provide a way to do dynamic method binding ("dynamic dispatch") if you really want it. In both it is accesed via pointers, which IMHO are kind of error-prone. It can also make things a bit of a pain to debug, as it is tough to tell from sources alone exactly what is getting called. So I avoid it unless I really need it.