Are the derived classes of `System.Exception` structurall equivalent to `System.Exception`? - c#

i am looking at
user defined exceptions and
system defined derived exceptions
Is it correct that all (or in the most cases) the derived classes of System.Exception, whether user defined or system defined, are structurally equivalent to their base class System.Exception, despite of them being non nominally equivalent?
Thanks.

No. When I inherit from System.Exception I add new variables to the derived class. Some stock exceptions do the same.

Not Necessarily (and likely not at all). Any class that inherits off of System.Exception will, by definition, implement everything that System.Exception implements. However, it will also have its own differences.
Let's take a look at a simple example: ArgumentNullException. This is a System namespace exception, so was defined by the creators of C#. Comparing System.Exception to System.ArgumentNullException shows differences. For example:
ArgumentNullException has an additional constructor with the signature ArgumentNullException(String, String), allowing you to pass in the name of the parameter that is null.
ArgumentNullException has an additional Property: ParamName, used to hold the name of the parameter that is null and caused the exception.
Since I am just looking at the highest level, there are also likely differences in how the common methods between these are implemented.
Suffice it to say, a child class will very rarely look identical to its parent.

Related

Why exactly are these "Special Classes"?

After reading this question asking what exactly a “Special Class” is, I am left with the question why the six classes System.Object, System.Array, System.Delegate, System.Enum and System.ValueType were chosen and hard-coded as special classes, preventing them from being used as constraints to generic classes or methods.
It is quite conceivable to understand why System.Object is in there; all classes inherit System.Object so there is no need to include it as a constraint. What I am unclear about is why the others were chosen to be part of this special classes category.
PS: The Special Classes raise the compile error CS0702 when an attempt is made to use them as constraints.
Those classes were already different before generic constraints, or even generics, were added to the .NET framework and support for them added to the C# language.
What each of them have in common, is that inheriting from them is different than with other types:
System.Object: You can't not inherit from this in C#.
System.Array: You inherit from this by creating an array of an existing type (Array x = new int[2]; etc.)
System.Delegate: You inherit from this by creating a delegate (which then derives from MulticastDelegate, also a "special type", which derives from Delegate).
System.Enum: You inherit from this by creating an enum.
System.ValueType: You inherit from this by creating a struct.
Now, note that aside from new() generic constraints are all about inheritance or implementation of interfaces (which is akin to inheritance in many ways). Indeed the other restrictions are that you can't use a pointer type, and you can't use a sealed type; two cases where you can't have a derived type anyway (though the the ban on sealed types is primarily because you are likely creating a generic type or method when you don't need too, and is an attempt to protect you from yourself).
And as such code that is based on inheritance features (as constraints are) when faced with special cases about inheritance will likely have to itself involve special cases. Those special cases were dealt with in the simplest way: By prohibiting them.
The value is also less in many of these cases:
System.Object: Since the only types that can't be converted to System.Object are pointer types, and these can't be used as generic parameters anyway, any such constraint is redundant.
System.Array: You can define in terms of element types: void DoSomethingWithArray<T>(T[] array) etc.
System.Delegate: Such would be useful, though in many cases we can define in terms of parameter and/or return types, but there are cases this doesn't catch.
System.Enum: Would be useful.
System.ValueType: Already dealt with; constrain as struct. Conversely we can also constrain as class to exclude this case so we've actually a "not inherited from…" option we don't have otherwise.
This is not to deny that being able to constrain in terms of Delegate, MulticastDelegate or Enum would not be useful (probably most so we Enum), but in terms of justifying the extra work to cover these types the others would give little or no benefit, so the benefit of less restrictions is reduced.

Empty interfaces and abstract class enforce structure

I've been looking into empty interfaces and abstract classes and from what I have read, they are generally bad practice. I intend to use them as the foundation for a small search application that I am writing. I would write the initial search provider and others would be allowed to create their own providers as well. My code's intent is enforce relationships between the classes for anyone who would like to implement them.
Can someone chime in and describe if and why this is still a bad practice and what, if any alternatives are available.
namespace Api.SearchProviders
{
public abstract class ListingSeachResult
{
public abstract string GetResultsAsJSON();
}
public abstract class SearchParameters
{
}
public interface IListingSearchProvider
{
ListingSeachResult SearchListings(SearchParameters p);
}
}
Empty classes and interfaces are generally only "usably useful" as generic constraints; the types are not usable by themselves, and generic constraints are generally the only context in which one may use them in conjunction with something else useful. For example, if IMagicThing encapsulates some values, some implementations are mutable, and some aren't, a method which wants to record the values associated with an IMagicThing might be written something like:
void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...}
where IIsImmutable is an empty interface whose contract says that any class which implements it and reports some value for any property must forevermore report the same value for that property. A method written as indicated could know that its parameter was contractually obligated to behave as an immutable implementation of IMagicThing.
Conceptually, if various implementations of an interface will make different promises regarding their behaviors, being able to combine those promises with constraints would seem helpful. Unfortunately, there's a rather nasty limitation with this approach: it won't be possible to pass an object to the above method unless one knows a particular type which satisfies all of the constraints, and from which object derives. If there were only one constraint, one could cast the object to that type, but that won't work if there are two or more.
Because of the above difficulty when using constrained generics, it's better to express the concept of "an IMagicThing which promises to be immutable" by defining an interface IImmutableMagicThing which derives from IMagicThing but adds no new members. A method which expects an IImmutableMagicThing won't accept any IMagicThing that doesn't implement the immutable interface, even if it happens to be immutable, but if one has a reference to an IMagicThing that happens to implement IImmutableMagicThing, one can cast that reference to the latter type and pass it to a routine that requires it.
Incidentally, there's one other usage I can see for an empty class type: as an identity token. A class need not have any members to serve as a dictionary key, a monitor lock, or the target of a weak reference. Especially if one has extension methods associated with such usage, defining an empty class for such purpose may be much more convenient than using Object.

Stylecop - Is class x in my inheritance hierarchy?

Is there a way to check if my element with elementtype class has a certain other class in his inheritance hierarchy?
My usecase is: I have to check if my Exceptions are prefixed with "Exception". To do so, i have to somehow determine if a certain class is an exception. The only way i can be sure is if it is inherited by the Exception class itself.
Checking the baseclass type for being an exception is easy enough, but imagine the following scenario:
class GenericMathException : Exception{}
class SpecificMathException : GenericMathException{}
The only information i can get about the SpecificMathException is that it's baseclass type is GenericMathException, but i can't go any further up in it's inheritance hierarchy.
The usual approach of reflection can't be used too, afaik.
So, anyone ever had to deal with this problem and found a solution? Or has any alternative approach to identify Exceptions?
Thanks in advance.
By its nature, StyleCop indeed works only with the contents of the file and can not use information from the assembly itself.
But, if you ask about "alternative approach to identify Exceptions", there is a rule in StyleCop+ which performs a checking very close to yours. You specify a list of base classes (Attribute, Exception, EventArgs and Stream by default), and it ensures that all classes inherited from them have the name that ends with ...Attribute, ...Exception and so on.
The checking works in the following way. If the name of the base class ends with a string from the list, it ensures that the name of the inherited class should also end with the same string. E.g., if it meets Class2 : InvalidOperationException or Class2 : SomeUnknownException, it will raise a violation in both cases.
Assuming that you follow this rule, all your inherited classes will always be named well, even if they are multi-inherited. The only thing that can not be checked in this way, is the situation where you deal with some classes not from "yours" assembly, that already have broken this rule. E.g., if some assembly has Class2 : Exception, and you reference this assembly as a binary (and do not have a chance to check it with StyleCop) then you will not be able to check if your Class3 inherited from Class2 should be prefixed with ...Exception.
But practice shows that the last issue is rather rare, so the method described above works really well for StyleCop.

Issue understanding the distinction between Methods, Generic Types etc

In the code below the "Move" public class derives fromthe generic type "Submit". "Submit" is a method, part of the DSS model, which handles messages and accepts two parameters, one is the message body and one is the message response.
My question is: How or WHY does a class derive from a method?!
It seems to me (since i'm only a beginner) "generic types" mean just this... any method or class (and by extension, any "block" of code) can become a type. Moreover there are NO types... everything is just a "class" which you can derive from (yet you probably can't overload string)
This basicly means that there are in fact NO methods OR types, but rather just classes (and some "sub"classes (ex-methods)) and you can derive from everything?!
Thank you.
I'm not looking for the expert "except this" answear where some small thing is not possible. I would like confirmation that this is, in fact, what 90% of the time, programmers are doing.
public class Move : Submit<MoveRequest, PortSet<DefaultSubmitResponseType, Fault>>
{
public Move()
{
}
public Move(MoveRequest body) : base(body)
{
}
}
You can not derive from a method. Submit<T, V, E> must be a class.
in a little more detail, Submit may be an "action" and therefore commonly thought of as a method, but in your context, Submit is indeed a class. This may be an example of the "Command" design pattern, in which a request for an action is encapsulated in an object and thus can be passed around and acted on by classes that handle the command.
Generics, conceptually speaking, are classes that are able to provide similar functionality among a set of "inner" types. The basic example is a Math class that can add, subtract, multiply and divide two variables of numeric type; you know, very advanced math you can't do any other way. There are a lot of numeric types in most type systems (in C# you have byte, short, int, long, float, double, and decimal, plus unsigned variations). Rather than implement a MathByte, MathInt, MathLong, etc with methods strongly defining the type they work on, or implementing a Math class that works with any Object (and thus requires you to examine the type of everything passed in to determine that you can work with the type), you can simply create a Math<T> class, where T can be any of the numeric types.
The type parameter T is different from method parameters; when you declare an instance of the class, you specify a type that the instance will be set up to handle. That instance can then only work with objects of the specified type, but you can instantiate a Math<byte> and a Math<decimal> to work with different types. Methods defined in Math specify input parameters of type T, and T is "replaced" at instantiation with the type declared when you instantiate the class.
Generics help support the DRY ("Don't Repeat Yourself") tenet of good coding practice, while maintaining type integrity. MathLong, MathInt, MathByte etc would all be similar or identical in their internal code; the main difference would be the type of the object they work on. Instead of rewriting the same class 10 times, you write one class that can be more concretely defined as to its working type by consumers of your class.
Hope this is a little more educational.
No, Submit is definitely not a method. A Class can only derive from another class, or implement an interface. So, Submit has to be either a class or an interface.

Can a class inherit from LambdaExpression in .NET? Or is this not recommended?

Consider the following code (C# 4.0):
public class Foo : LambdaExpression { }
This throws the following design-time error:
Foo does not implement inherited abstract member
System.Linq.Expressions.LambdaExpression.Accept(System.Linq.Expressions.Compiler.StackSpiller)
There's absolutely no problem with public class Foo : Expression { } but, out of curiosity and for the sake of learning, I've searched in Google System.Linq.Expressions.LambdaExpression.Accept(System.Linq.Expressions.Compiler.StackSpiller) and guess what: zero results returned (when was the last time you saw that?). Needless to say, I haven't found any documentation on this method anywhere else.
As I said, one can easily inherit from Expression; on the other hand LambdaExpression, while not marked as sealed (Expression<TDelegate> inherits from it), seems to be designed to prevent inheriting from it. Is this actually the case? Does anyone out there know what this method is about?
EDIT (1): More info based on the first answers - If you try to implement Accept, the editor (C# 2010 Express) automatically gives you the following stub:
protected override Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor)
{
return base.Accept(visitor);
}
But you still get the same error. If you try to use a parameter of type StackSpiller directly, the compiler throws a different error: System.Linq.Expressions.Compiler.StackSpiller is inaccessible due to its protection level.
EDIT (2): Based on other answers, inheriting from LambdaExpression is not possible so the question as to whether or not it is recommended becomes irrelevant. I wonder if, in cases like this, the error message should be Foo cannot implement inherited abstract member System.Linq.Expressions.LambdaExpression.Accept(System.Linq.Expressions.Compiler.StackSpiller) because [reasons go here]; the current error message (as some answers prove) seems to tell me that all I need to do is implement Accept (which I can't do).
I just looked at the LambdaExpression class in .NET 3.5 using Reflector and the class has only an internal constructor. When I try your code, I'm getting an error "The type 'System.Linq.Expressions. LambdaExpression' has no constructors defined", so on .NET 3.5 this cannot be done (leaving aside the question whether it would be useful to do it).
In .NET 4.0 it behaves as you described. However, the Accept method is internal and so is the StackSpiller type. This again means that you simply can't do this (although it isn't clear from the compiler error message). It is worth noting that the class still has only internal constructor on .NET 4.0. The compiler only finds another reason why you can't override it (and doesn't worry about that any more).
EDIT: Regarding the StackSpiller type - it is internal, so you don't really need to worry about it. However, it looks that the type comes from DLR, which is a .NET 4.0 component that now handles compilation of lambda expressions (and also C# 4 dynamic). Anyway, DLR is open-source, so here is what a summary comment says about this type:
Expression rewriting to spill the CLR stack into temporary variables
in order to guarantee some properties of code generation, for
example that we always enter try block on empty stack.
This means that it is used to do some pre-processing of lambda expressions when they are compiled using the Compile method. You can get the source code from CodePlex.
The error message means that LambdaExpression itself is an abstract class. You need either supply your body for abstract method Accept, or declare Foo as abstract.
However, list of LambdaExpression members on MSDN doesn't list Accept.
Well, the error basically tells us that LambdaExpression is an abstract class, which means that in order to derive from it, you'd have to implement all abstract members. In this case, the Accept method.
It is neither recomended or allowed. The LambdaExpression type has several internal abstract members and an internal constructor. This prevents you from deriving from it from a different assembly unless their is a friend relationship (which there is not in this case)

Categories

Resources