Explicitly cast base class to derived class - c#

Problem: I have 2 types which are result sets of 2 different procedures in DB:
Proc1Result, Proc2Result (We had to split them - but they are basically the same as comes for input/output)
I then decided that I could make use of an interface to switch between needed procedures on runtime - but this means I would need 1 common type to which i could convert Proc1Result and Proc2Result
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result) - I derived this class from one of the results:
public class DerivedClassForInterface : Proc1Result {}
Then I implemented explicit cast from the 2nd proc which works fine, but when I want to implement explicit cast from base class to derived class - it wont allow me (since it kinda already "does" - but it fails at runtime):
public class DerivedClassForInterface : Proc1Result
{
//ok - and works as expected
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
return new DerivedClassForInterface
{
...
};
}
//fail: 'user-defined' conversations to or from a base class are not allowed
public static explicit operator DerivedClassForInterface(Proc1Result v)
{
return new DerivedClassForInterface
{
...
};
}
}
so this works:
//result2 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result2;
//compiles - works as expected at runtime
but this does not:
//result1 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result1;
//compiles - conversation fails at runtime
So why I can not write my own explicit operator if you can not cast from base class to derived class?
Interesting that compiler allows me to cast from base to derived class, and yet it does not work at runtime.
Probably I will go just for simple functions which will do the "casting" for me. Anyone can suggest a better solution (keep in mind that I would like to keep "DerivedClassForInterface" to obey changes in "Proc1Result" (or "Proc2Result" - doesn't matter))
EDIT
#Peter Duniho - Here the types "Proc1Result" and "Proc2Result" are generated as results from stored procedures (linq2sql). I would like to have a code which I wont need to touch when output of those procedures change (since there are bunch of procedures we need to segment - and implementing new modules could and often does add more output).
Proc1 and Proc2 are basically same stored procedures (they require exactly the same input and provides same output (type-wise not data-wise)). Both of them work with different segments of data and are required to be separate.
Sorry for making this confusing (was at end of my working day...) and not clarifying - the question here actually is:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
Here is "Minimal, Complete, and Verifiable code example" (thanks for the link):
//results from stored procedures in database which got splitted appart (linq 2 sql)
class Proc1Result { }
class Proc2Result { }
//
class DerivedClassForInterface : Proc1Result
{
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
//this part would be exported in generic function
var derivedClassInstance = new DerivedClassForInterface();
var properties = v.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedClassInstance.GetType().GetProperty(property.Name);
if (propToSet.SetMethod != null) propToSet.SetValue(derivedClassInstance, property.GetValue(v));
}
return derivedClassInstance;
}
}
interface IProcLauncher
{
DerivedClassForInterface GetNeededData();
}
class ProcLauncher1 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc1Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class ProcLauncher2 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class Program
{
static void Main(string[] args)
{
bool causeInvalidCastException = true;
IProcLauncher procedureLauncher;
if (causeInvalidCastException) procedureLauncher = new ProcLauncher1();
else procedureLauncher = new ProcLauncher2();
var result = procedureLauncher.GetNeededData();
Console.WriteLine("I got here!");
}
}
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
I can solve this - let say - by just 1 generic function which will handle conversation for all cases, but the question is above in bold.

I implemented the converting the following way:
class BaseConverter
{
protected T Convert<T, X>(X result)
{
var derivedClassInstance = Activator.CreateInstance<T>();
var derivedType = derivedClassInstance.GetType();
var properties = result.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(derivedClassInstance, property.GetValue(result));
}
}
return derivedClassInstance;
}
protected List<T> Convert<T, X>(List<X> listResult)
{
var derivedList = new List<T>();
foreach (var r in listResult)
{
//can cope with this - since there will not ever be many iterations
derivedList.Add(Convert<T, X>(r));
}
return derivedList;
}
}
So interface implementation classes would inherit from it:
class ProcLauncher2 : BaseConverter, IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
//usage (works for single result or list if I need a list returned):
return Convert<DerivedClassForInterface, Proc2Result>(dataFromDb);
}
//other methods...
}
Yet - it is not clear for me - why there is already cast from base class to derived - if that does not work. Imo - it should not be there and throw error at compile time.

I don't understand your question very well. You seem to say that the compiler lets you write the code you posted, but that it fails at runtime. This isn't my experience. I get a compile-time error on the explicit conversion operation for the base class:
error CS0553: 'Derived.explicit operator Derived(Base1)': user-defined conversions to or from a base class are not allowed
Seems pretty clear to me. As for why you aren't allowed to write code like that, you'd have to ask the language designers to know for sure, but it seems like a reasonable restriction to me. There already is a safe, built-in conversion from any base class to a derived class of that base class, as long as the base class instance is in fact an instance of the derived class. It would be confusing and likely to lead to bugs if programmers were allowed to make additional conversions, never mind greatly complicate the language specification's rules for the casting/conversion operator.
As for the broader problem, I don't understand the approach you've chosen. You're designing the classes exactly upside-down from the way one would normally do this. If you have a number of classes that all have shared members, you want to be able to treat all those classes as the same in some context, and you want to be able to implement those shared members exactly once and share them among the other classes, you would put all those members in a single base class, and then derive all your various types from that class.
I don't even see how your current approach addresses this concern:
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result)
Since Proc2Result doesn't inherit Proc1Result, if Proc1Result changes, you'll have to go change Proc2Result to match anyway. And any other similar types. And the DerivedClassForInterface class. And you have to change all the explicit operators. How is that better?
I would think you would prefer something like:
class BaseClassForInterface
{
// declare all shared members here
}
class Proc1Result : BaseClassForInterface { ... }
class Proc2Result : BaseClassForInterface { ... }
Then, for each new Proc...Result class, you simply inherit the base class, no need to re-write the members, and the conversion from each Proc...Result class is trivial. You don't even need to use the casting/conversion operator; the language already knows how to implicitly convert from derived classes to base classes, because the derived classes are the base classes.
This is, in fact, the standard way to use OOP. It's one of the most fundamental features of any OOP language.
If that doesn't get you back on track, you'll need to improve the question, so that it's more clear what you are doing and why. You'll also need to provide a good Minimal, Complete, and Verifiable code example that clearly illustrates your question, explaining precisely what that code does and what you want it to do instead.
Addendum:
Thanks for the edit. Your question is a lot more specific and clear now. I still have questions, but at least I understand the real context.
It seems to me that you already understand most of the basic answer to your question:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
I.e. yes, I believe the language disallows this because there is already a built-in cast, and yes the exact approach you seek is doomed to not work.
As far as this part goes:
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
If I understand the first point, this is why you inherit one of the stored procedure types. So that you get the property declarations for free. Seems a little hacky to me, but I admit I do understand the motivation.
As I understand the third point above and your statement after in your post, you already know how you can write a generic method to do the conversion. E.g. something like:
DerivedClassForInterface ConvertToClassForInterface<T>(T t)
{
DerivedClassForInterface result = new DerivedClassForInterface();
Type resultType = typeof(DerivedClassForInterface);
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var propToSet = resultType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(result, property.GetValue(t));
}
}
return result;
}
I.e. essentially the code you show in your explicit operator (with some minor cleanup/optimization). Or maybe you aren't using the term "generic" literally, and just mean "general purpose". Obviously there's very little in the above that really benefits from the method being generic; you could just as easily use GetType() on the parameter, just as your explicit operator does.
Unfortunately, I don't know how the criteria "Got to be injectable" fits in here. Injectable, how? Do you mean you want to inject the code somewhere else? Or do you mean that the code needs to be compatible with an AOP system, or some other form of code injection applied to it?
Ignoring that part, which I don't understand, I would actually just leverage the compiler and runtime to do all the heavy lifting for me (including caching the reflection stuff, which in your code is going to be very slow). You could write a class like this:
class Wrapper
{
private dynamic _data;
public string Value { get { return _data.Value; } }
public Wrapper(dynamic data)
{
_data = data;
}
}
Given a couple of other classes like this:
class Result1
{
public string Value { get; set; }
}
class Result2
{
public string Value { get; set; }
}
Then you can use it like this:
Result1 r1 = new Result1 { Value = "result 1" };
Result2 r2 = new Result2 { Value = "result 2" };
Wrapper w1 = new Wrapper(r1), w2 = new Wrapper(r2);
Console.WriteLine("w1 result: " + w1.Value);
Console.WriteLine("w2 result: " + w2.Value);
I.e. just create an instance of Wrapper, passing the relevant object (in your case, this would be the generated type's from the stored procedure). The downside is, of course, that you do have to add properties to the Wrapper type to match your stored procedure. But I'm not convinced that's a bad thing. Even if you've somehow arranged it so that none of the rest of the code has to change, it's a relatively minor maintenance task.
And I suspect that altering the stored procedure requires changes elsewhere in the code anyway, to explicitly refer to the properties. Because after all, if the rest of the code is similarly completely agnostic regarding the specific class members (i.e. uses reflection all the way), then you could just pass the result objects around as object types, and not worry about the wrapper at all.

Related

C# Interface Implicit Promotion similar to unboxing, using a known hierarchical pattern of Interfaces:

Weird question here - something that's come up, due to the environment I'm working within.
A bit of a preface:
I am going to abuse well-known abstractions from the Taxonomic rank to describe the situation I'm stuck with - by design decisions which were not my own, and are now Live in production on high-use data processing systems.
I'm working on using (consuming) an API that was designed by others at work, I have no input on, and just need to be able to write code against.
This API is actually automatically generated C# code that's been compiled, and defines a complex interfacing type system which describes
1 Top-level Interface, hundreds of Second-level interfaces, And hundreds of Third-level interfaces, with a relationship of 1:1 on the Second-level interfaces and Third-level interfaces - IE, for every second-level interface, there is exactly 1 third-level interface, which also implements the Second-level Interface, and the top-level interface explicitly.
I will describe my conundrum (roughly) using the first 3 ranks within the field of biology's Taxonomic rank system.
A Pattern I will be using here:
I%Domain% Is kind of a generalized stub, indicating a collection of interfaces of some arbitrary Domain (IArchaea, IBacteria, IEukarya). It could be any of these three (and in reality, there are literally hundreds).
I%Kingdom% Is kind of a generalized stub (similar to I%Domain%), which if I%Domain% is actually IEukarya, would contain patterns similar to IFungi, IProtista, IPlantae, IAnimalia. The metaphor here breaks down, as in reality, there is exactly 1 Interface of this third tier that directly correlates to the known interface of the second tier. However, for the purposes of promotion, this is actually unimportant - I'm merely pointing out the metaphor's inconsistency.
// Implemented, and "Cement". Our algorithm fundamentally works with
// IOrganism as the main type for everything, using reflection to
// iterate properties, due to the needs presented.
// Consider to be Tier-1 Interface.
interface IOrganism { /*...*/ }
// Implemented, and "Nebulous" (Could be IArchaea, IBacteria, IEukarya, etc...)
// Will never actually be IDomain, but will rather be one of
// IArchaea, IBacteria, IEukarya, in a more "generic" approach.
// Note: The %Domain% syntax is *is indicative of a
// "stub" for any arbitrary pre-defined Domain-like
// interfaces. See the pattern described above.
// Consider to be Tier-2 Interface, which is "inherited"
// from by exactly 1 Tier-3 Interface.
Interface I%Domain% : IOrganism { /*...*/ }
// Implemented, and "Nebulous". See above on the Pattern section,
// as well as the comment on I%Domain%.
// Note: The %Kingdom% is indicative of a "stub"
// for any arbitrary pre-defined Kingdom interfaces.
// Consider to be a Tier-3 Interface, for which exactly 1 exists which
// implements each Tier-2 Interface.
interface I%Kingdom% : I%Domain%, IOrganism { /*...*/ }
All work is being done upon the IOrganism interface, but it is known that every input interface to the described method (below) are also I%Kingdom% (which is also I%Domain%).
I need a Method in C# which can receive an input IOrganism, assume it is an I%Kingdom%, and promote it to the up-casted I%Domain% type, in a generalized fashion, returning it as an IOrganism. This is conceptually similar to unboxing, but with a 3-tier system, and defined via hierarchical patterns amongst Interfaces, without particular regard to underlying object-types, only interface declarations.
// Given an IOrganism which is provided as a sub-typed
// I%Kingdom%instance , returns the input object as a
// Type-cast I%Domain%, and stored as an IOrganism.
public static IOrganism PromoteType(IOrganism organismAs%Kingdom%)
{
// Get the type of the base as the current base type.
// Is approximately typeof(I%Kingdom%), but
// Isn't actually a generic, and rather refers to
// An arbitrary instance of an I%Kingdom%-type
// of interface.
Type baseType = organismAs%Kingdom%.GetType();
// Throw exception if the type provided is not the expected type
// Note: type-checking is an abstraction,
// we need another logical statement to determine if it
// is the I%Kingdom% "generalized" interface type
// Assume the actual statement works.
if (baseType != typeof(I%Kingdom%))
{
// assume a more descriptive error string here.
string error = "Provided object was of an invalid type."
throw new InvalidArgumentException(string.Format(error));
}
// Stores the type of I%Domain%, inherantly.
// Use LinQ to retrieve the matching interited type.
// Note: The Name.Equals()-logic on "IDomain" is an abstraction
// of the real logic, we actually have another logical statement
// to determine if it is really the I%Domain%-pattern in
// a more "generalized" fashion. Assume the "real"
// variant of this statement works properly.
Type upcastTypeAsIDomain = baseType.GetInterfaces()
.FirstOrDefault(
currInterfaceType => currInterfaceType.Name.Equals("I%Domain%"));
// Note: For the third time, I%Domain% here is a logical abstraction -
// There is another statement I'm using which works,
// I'm just representing the effective statement
// Relative to the question's context.
if (upcastTypeAsIDomain != typeof(I%Domain%))
{
// A more meaningfull error message exists in reality.
string error = "Provided object didn't implement the proper I%Domain% interim type.";
throw new InvalidArgumentException(string.Format(error));
}
return /*This is the line I need help on*/;
}
My question is on that return statement, how do I perform a "generic" (not to be confused with C# Generics) type-cast on the provided IOrganism, known to be an I%Kingdom% order of Interface, and return it as if it were an I%Domain%, conceptually similar to C#'s Unboxing, knowing the Type of the object cemently as IOrganism, but then casting it as the Type of the declared type, and storing it as if it's an IOrganism, but where the GetType() would return the corresponding I%Domain%, and not the true underlying I%Kingdom%?
Reflection is fine to use here - I am aware of the performance cost, but that won't be an issue in the context this is running.
I envision some mythical syntax similar to:
// Obviously not a real Compileable line of C# - this is a pattern only.
IOrganism organismAsUpcastDomain = CAST_FROM_I%Kingdom%_TO_I%Domain%;
Is there any sort of "generic"-cast (not to be confused with C# generics) which convert from 1 Type (as an interface) to another type (also as an interface), pretending the underlying object's base type is now the second type, assuming the hierarchical definitions are correct? That way when I store this organismAs%Kingdom% within an IOrganism, the organismAs%Kingdom%.GetType() would return the type of I%Domain%, instead of I%Kingdom%, despite fundamentally still being an I%Kindom% internally?
The context in which this program runs will not be "live", in the sense that user-requests actively force the logic to execute, but rather, will be pre-run by developers, generate a cache-file which represents the results of this processing, and then can be looked up in real-time as per request, which will be hammered hundreds of thousands, to millions of times per day. It needs to be able to process the promotion of an arbitrary interface sub-type(depth 3) to 1 layer up (depth 2) (and stored within the tier 1 interface type).
It may not even be possible to do this in C#, as I'm unsure how well the underlying .NET Framework differentiates between the fundamental interface-type as if it is the underlying object's base type, and the type it's being stored as, allowing you to "pretend" the object of type C is really type B, stored within Type A, allowing you to invoke .GetType() on an instance of A, which would return a Type equal to typeof(B), while really being an object of Type C, effectively making it lie about its own heritage.
This may look similar to Covariance and Contravariance at first, but is different, due to the fact that I'm working with arbitary Interface Types that are behaviorally and hierarchically similar to I%Domain% and I%Kingdom%, while describing them utilizing reflection.
Thanks for even reading the post here, as it's
Long
Convoluted
Abuses the term "generic" when not actually referring to true C# Generics
Should be unnecessary, but due to the environment I'm programming within, (I'm writing a program that needs to use reflection on the declared types in a general fashion to perform work on all inputs regardless of types, following certain pre-known patterns and hierarchies, on a data structure that could literally change at any time, to perform generalized work on this abstraction).
So I've refactored my code base allowing me to just return the reflected interface parent type (rather than attempt to perform some ungodly generic-cast), making the answer to this question a moot point for my needs, but I've also now come up with an answer that lets you provide an alias type for an object of any other type. At this point it's almost contrived, but if for some reason, if you're using reflection and want have an easy mechanism to track which degree within a complex inheritance chain your current object is being aliased as, you can use the following classes:
public abstract class TypeAlias
{
public virtual object ValueAsObject { get; set; }
public virtual Type PresentingType { get; set; }
}
public class TypeAlias<T> : TypeAlias
where T : class
{
private T underlyingTypeSafeObject;
public TypeAlias()
: base()
{
base.PresentingType = typeof(T);
}
public T TypeSafeObject
{
get
{
return this.underlyingTypeSafeObject;
}
set
{
this.underlyingTypeSafeObject = value;
if (base.PresentingType == null && value != null)
{
base.PresentingType = value.GetType();
}
}
}
public override object ValueAsObject
{
get
{
return this.underlyingTypeSafeObject;
}
set
{
// returns null if cast conversion fails - not type-safe on the TypeAlias level.
this.underlyingTypeSafeObject = value as T;
}
}
public override Type PresentingType
{
get => base.PresentingType; set => base.PresentingType = value;
}
}
With that convention, and with the following interfaces (and implementations) in mind:
public interface IOrganism
{
string Be();
}
public interface IDomain : IOrganism
{
string DomainName { get; set; }
}
public interface IKingdom : IDomain, IOrganism
{
string KingdomName { get; set; }
}
public class SeventhDimension : IDomain
{
private string domainName = "7th Dimension";
string IDomain.DomainName { get => domainName; set => domainName = value; }
public virtual string Be()
{
return string.Format("{0} Exists.", this.domainName);
}
}
public class KingdomHyrule : SeventhDimension, IKingdom, IDomain
{
private string kingdomName = "Hyrule";
string IKingdom.KingdomName { get => kingdomName; set => kingdomName = value; }
public virtual string Be()
{
string s = base.Be();
s += string.Format(" Also, {0} Exists.", this.kingdomName);
return s;
}
}
We can now have the following code to provide a different alias, which we can control the presentation of, to allow for reflection on differing degrees upon the inherited pedigree of any particular implementation of an object:
// Create a Hyrule Kingdom, which is also a SeventhDomain,
// and IOrganism, IKingdom, IDomain.
IOrganism testOrganism = new KingdomHyrule();
Console.WriteLine(testOrganism.Be());
// Construct a TypeAlias, which by default presents
// the type of the container you store it as,
// using Generics.
TypeAlias alias = new TypeAlias<SeventhDimension>()
{
ValueAsObject = testOrganism
};
Console.WriteLine();
// Grab the real type of the testOrganism,
// which will be KingdomHyrule
Console.WriteLine(testOrganism.GetType().Name);
// Grab the faked type of testOrganism,
// which will be SeventhDimension, due to
// the construction of the Alias.
Console.WriteLine(alias.PresentingType.Name);
// Could be retrieved using reflection on Implementing Types
alias.PresentingType = typeof(IOrganism);
Console.WriteLine(alias.PresentingType.Name);
/* Output:
* 7th Dimension Exists. Also, Hyrule Exists. | from testOrganism.Be();
*
* KingdomHyrule | from testOrganism.GetType().Name;
* SeventhDimension | from alias.PresentingType.Name;
* IOrganism | from alias.PresentingType.Name, after assignment
* */
As I said above - I no longer even need this, but the classes TypeAlias and TypeAlias<T> make it easy to loosely couple an arbitrary instance of a class, and have it present any other type (which by convention could be used to allow you to use reflection to grab properties / methods out of reflectively detected base types).

Why generic collection of objects cannot be assigned generic collection of strings in C# [duplicate]

I defined the following class:
public abstract class AbstractPackageCall
{
...
}
I also define a subclass of this class:
class PackageCall : AbstractPackageCall
{
...
}
There are also several other subclases of AbstractPackageCall
Now I want to make the following call:
List<AbstractPackageCall> calls = package.getCalls();
But I always get this exception:
Error 13 Cannot implicitly convert type 'System.Collections.Generic.List<Prototype_Concept_2.model.PackageCall>' to 'System.Collections.Generic.List<Prototype_Concept_2.model.AbstractPackageCall>'
What is the problem here? This is the method Package#getCalls
internal List<PackageCall> getCalls()
{
return calls;
}
The simplest way to understand why this is not allowed is the following example:
abstract class Fruit
{
}
class Apple : Fruit
{
}
class Banana : Fruit
{
}
// This should intuitively compile right? Cause an Apple is Fruit.
List<Fruit> fruits = new List<Apple>();
// But what if I do this? Adding a Banana to a list of Apples
fruits.Add(new Banana());
The last statement would ruin the type safety of .NET.
Arrays however, do allow this:
Fruit[] fruits = new Apple[10]; // This is perfectly fine
However, putting a Banana into fruits would still break type safety, so therefor .NET has to do a type check on every array insertion and throw an exception if it's not actually an Apple. This is potentially a (small) performance hit, but this can be circumvented by creating a struct wrapper around either type as this check does not happen for value types (because they can't inherit from anything). At first, I didn't understand why this decision was made, but you'll encounter quite often why this can be useful. Most common is String.Format, which takes params object[] and any array can be passed into this.
In .NET 4 though, there's type safe covariance/contravariance, which allows you to make some assignments like these, but only if they're provably safe. What's provably safe?
IEnumerable<Fruit> fruits = new List<Apple>();
The above works in .NET 4, because IEnumerable<T> became IEnumerable<out T>. The out means that T can only ever come out of fruits and that there's no method at all on IEnumerable<out T> that ever takes T as a parameter, so you can never incorrectly pass a Banana into IEnumerable<Fruit>.
Contravariance is much the same but I always forget the exact details on it. Unsurprisingly, for that there's now the in keyword on type parameters.
Now if you want to make the following call:
List<PackageCall> calls = package.getCalls();
// select only AbstractPackageCall items
List<AbstractPackageCall> calls = calls.Select();
calls.Add(new AnotherPackageCall());
I call this generalization.
Also, you can use this more specific:
List<PackageCall> calls = package.getCalls();
// select only AnotherPackageCall items
List<AnotherPackageCall> calls = calls.Select();
calls.Add(new AnotherPackageCall());
Implement this using extension method:
public static class AbstractPackageCallHelper
{
public static List<U> Select(this List<T> source)
where T : AbstractPackageCall
where U : T
{
List<U> target = new List<U>();
foreach(var element in source)
{
if (element is U)
{
target.Add((U)element);
}
}
return target;
}
}
Why what you try does't work
You are asking the compiler to treat a List<PackageCall> as a List<AbstractPackageCall>, which it is not. It's another matter that each of those PackageCall instances is in fact an AbstractPackageCall.
What would work instead
var calls = package.getCalls().Cast<AbstractPackageCall>().ToList();
Why what you try will never be allowed to work
Even though each item inside the return value of package.getCalls() derives from AbstractPackageCall, we can't treat the whole list as List<AbstractPackageCall>. Here's what would happen if we could:
var calls = package.getCalls(); // calls is List<PackageCall>
List<AbstractPackageCalls> apcs = calls; // ILLEGAL, but assume we could do it
apcs.Add(SomeOtherConcretePackageCall()); // BOOM!
If we could do that, then we could add a SomeOtherConcretePackageCall to a List<PackageCall>.
Because List<PackageCall> does not inherit from List<AbstractPackageCall>. You can use the Cast<>() extension method, like:
var calls = package.getCalls().Cast<AbstractPackageCall>();
You cannot perform this conversion, because a List<AbstractPackageCall> can contain anything that derives from AbstractPackageCall, while a List<PackageCall> cannot -- it can only contain things that derive from PackageCall.
Consider if this cast were allowed:
class AnotherPackageCall : AbstractPackageCall { }
// ...
List<AbstractPackageCall> calls = package.getCalls();
calls.Add(new AnotherPackageCall());
You just added an AnotherPackageCall into a List<PackageCall> -- but AnotherPackageCall does not derive from PackageCall! That's why this conversion is not allowed.

How to avoid using the is operator in c# when my method returns a base type?

I have an abstract base class P. I have two classes that inherit P called I and O.
I have a Get() method in my repository that returns P. This method always returns an instance of either I or O depending on a value.
public P Get(string pci)
{
var a = GetAByPCI(string pci);
if(a == 1)
return new I();
else if(a == 2)
return new O();
else
// throw exception here.
}
When I call this method from another location I need to check and cast the type.
P p = PRepository.Get("200");
if(p is I)
I i = (I)p;
I'd like to avoid having to check and downcast every time p above is used. I feel as though I'm doing some fundamentally wrong here, but am not certain.
Update:
The derived types I & O have additional properties that need to be used but only pertain to that specific type. P has many abstract properties that are implemented in inheriting types. Downcasting is the only way I can get to the concrete types as needed?
Maybe the logic is entirely wrong.
The whole point of having a base class is to avoid having to deal with the subclass itself. Just add an abstract method to the base class and have it implemented in the sub-classes. This way, the calling code will simply call the method without having to do any casts. This is basic polymorphism.
What is your intention? It seems you are not making proper use of inheritance.
If you return a P object from your methods, you either need to downcast or return the derived types.
You are correct to be suspect of down casting.
I would look at the template method design pattern. If you have a base class it should be used to hide the details of the subclass.
So maybe you have a method in your base class called Execute(). Inside the base class the execute method calls some protected methods, lets say Method1(), and Method2(). Method 1 would contain the shared code, method two would be abstract and the child classes would have to execute it. Then when you get your instance back you just call Execute. The proper Method2() will run without you having to cast downward.
public abstract class MyBaseClass
{
public void DoSomething()
{
//Here's a bunch of stuff I have to do everytime
DoSomethingTypeSpecific();
//I could do more stuff if I needed to
}
protected abstract void DoSomethingTypeSpecific();
}
class MyBaseClassOne : MyBaseClass
{
protected override void DoSomethingTypeSpecific()
{
Console.WriteLine(1);
}
}
class MyBaseClassTwo : MyBaseClass
{
protected override void DoSomethingTypeSpecific()
{
Console.WriteLine(2);
}
}
I would also think about using the Decorator pattern and composition instead of using inheritance.
Nevertheless you still need a cast if you want to access the properties that are not part of the base class.
If all above solutions not fitting your requirements and you don't want to change the base class (adding properties from derrived classes) then you should also think not only about your inheritance design as mentioned by most comments... you should also look for your factory/repository implementation. Is this repository doing the thing you need? Why not add a GetI() and GetO()?
For eample Linq allows you to query and filter a List with using .OfType and you get only elements of Type T.
You can add a specific Get Method with type info (e.g. with generics as I did in my example) and an additional condition.
public T Get<T>(string pci, int c)
{
var a = GetAByPCI(string pci);
if(a == c)
return new T();
else
// throw exception here.
}
Call the method Get with the generic param. The problem of this solution here is that you need to know the condition at the call time and this does not handle "special constructions" (e.g. constructor with params for T). Anyway this could be solved with the factory pattern, too.
I i = PRepository<I>.Get(1, "200"); // create a new I(), only if 1 fits GetAByPCI()
O o = PRepository<O>.Get(2, "123"); // create a new O(), only if 2 fits GetAByPCI()
// can do anything with the concrete type
You could also move the condition out of the repository/factory call with the strategy pattern (already mentioned in my answer above).
It is also possible to wrap up the "as" behind the generic method (I show you how even if I would not recommend it in most cases).
public T Get<T>(string pci)
{
return this.Get(pci) as T; // your method with trying to cast to concrete type
}
This way you can get the implementation as follows:
I i = PRepository<I>.Get("200");
if (i != null)
{
// do I specific tasks
}
It is not possible to eleminate the cast without putting the properties into the base class but you can use the strategy pattern to decouple the object creation (see my question and answer here for an example how to do this). The example shows how to decouple the switch-case but you can do the same thing with the strategy pattern for analysing the result of the context, so you can hide the cast.
public static class A
{
// please note: some example in related to your question
// and the strategy pattern provided at the link
public static P GetI(int a)
{
if (a == 1)
return new I();
else
return null; // <- this is important for evaluation
}
// can put this method anywhere else, also into another class
public static P GetO(int a)
{
if (a == 2)
return new O();
else
return null; // <- this is important for evaluation
}
public static bool Condition(string pci)
{
return !string.IsNullOrEmpty(pci); // could eval different states, values
}
}
Then it is possible to divide the as/is logic into separate methods/classes and the calling class (e.g. controller, client) doesn't need to know all the different specializations.
The following code shows how to create the context. See my posting here for the implementation details of Strategy and Context class.
var strategyI = new Strategy<int, P>(A.Condition, A.GetI);
var strategyO = new Strategy<int, P>(A.Condition, A.GetO);
var strategies = new List<Strategy<int, P>> {strategyI, strategyO};
var context = new Context<int, P>(strategies.ToArray());
var result = context.Evaluate(1); // should return a new I(), with 2 as param a new O()
// once you get the result you can create a new context to work with the result
var strategyWorkI = new Strategy<P, P>(Condition, WorkWithI);
var stragegiesForWork = new List<Strategy<P, P>> {strategyWorkI} // could be more than one
var workContext = new Context<P, P>(strategiesForWork.ToArray());
var p = workContext.Evaluate(result); // does the right thing, but
// no need to know class I here (only P)
if (p == null)
// seems to be something went wrong, throw? ...
And here is the decoupling for the cast but you still need a cast at this point.
public static P WorkWithI(P p)
{
var i = p as I; // I would prefer as instead of is (see boxing/unboxing in .net)
if (i != null)
{
// do what you want with concrete class I in i
}
return i; // <- this is important for Evaluation
}
Anyway... there is still Point in the code with an is/as, but it does not influence your controller / manager etc. (keeps code flexible and pluggable, e.g. via Dependency Injection)
... I can provide a full example if you can't understand my short description.

C# simpler run time generics

Is there a way to invoke a generic function with a type known only at run time?
I'm trying to do something like:
static void bar()
{
object b = 6;
string c = foo<typeof(b)>();
}
static string foo<T>()
{
return typeof (T).Name;
}
Basically I want to decide on the type parameter only at run time, but the function I'm calling depends on the type parameter.
Also I know this can be done with reflections... but it's not the nicest solution to the problem...
I'm sort of looking for dynamic features in C#...
I'm writhing a bridge between two classes the first one is basically a big tree with different types of of objects (composite by interface) the other is a sort of a "super visitor".
the supper visitor accepts key-value dictioneries that map types to object it looks like:
dic.Add(object value)
and T is not necessarily the type of the value... a lot of times it isn't...
I know it's written poorly, but i can't fix it...
I can work around it, but only at runtime...
I already did it with reflections, but if there's a better way to do it without them i would be happy to learn...
Thank you
This is a bit of a hack but you can get dynamic to do the reflection work for you by something like,
class Program
{
static void Main(string[] args)
{
var b = 6;
var t = (dynamic)new T();
var n = t.Foo(b);
}
class T
{
public string Foo<T>(T a)
{
return typeof(T).Name;
}
}
}
Here the dynamic call will extract the type of b and use it as a type parameter for Foo().
You can use dynamic keyword if you're using .NET 4. In a word, the type of the variable will be resolved at run time so it is a super generic type ;) You can read a article here or read the MSDN documentation
Saly refelction is THE solution to the problem, whether it is nice or not is irrelevant here. It is the runtime designed mechanism to achieve exactly this. As there is no parameter or generics to use as input, this is the only way to do it - it is also senseless. As in: your example is bad. Because in the example the type is hardcoded.
If the method where b exists has b as generic parameter, the type is available for passing to foo. If not - reflection is THE way to go, albeit the syntax looks clumsy. Only one time, though.
This I believe is the only way:
var foo = typeof(Foo<>).MakeGenericType(typeof (bar));
You can set up a class which takes a type parameter at run time which can be used in the methods in that class.
public class GenericClass<T>()
{
ICommonInterface TheObject;
public GenericClass(T theObject)
{
TheObject = theObject;
}
public string GetName()
{
return TheObject.Name;
}
}
But this is only really useful if the Types being passed in share interfaces so have common properties between them. In your example it seems that relection is the answer as depending on the type you want to access specific properties.

Suggestions on Working with this Inherited Generic Method

We have inherited a project that is a wrapper around a section of the core business model.
There is one method that takes a generic, finds items matching that type from a member and then returns a list of that type.
public List<T> GetFoos<T>()
{
List<IFoo> matches = Foos.FindAll(
f => f.GetType() == typeof(T)
);
List<T> resultList = new List<T>();
foreach (var match in matches)
{
resultList.Add((T)obj);
}
}
Foos can hold the same object cast into various classes in inheritance hierarchy to aggregate totals differently for different UI presentations. There are 20+ different types of descendants that can be returned by GetFoos.
The existing code basically has a big switch statement copied and pasted throughout the code. The code in each section calls GetFoos with its corresponding type.
We are currently refactoring that into one consolidated area, but as we are doing that we are looking at other ways to work with this method.
One thought was to use reflection to pass in the type, and that worked great until we realized the Invoke returned an object, and that it needed to be cast somehow to the List <T>.
Another was to just use the switch statement until 4.0 and then use the dynamic language options.
We welcome any alternate thoughts on how we can work with this method. I have left the code pretty brief, but if you'd like to know any additional details please just ask.
Update
The switch statement was originally using strings and the first pass was moving it into a Presenter with something like this: (No refactoring done on the switch, just where the data went).
// called on an event handler in FooPresenter
// view is the interface for the ASPX page injected into FooPresenter's constructor
// wrapper is the instance of the model wrapper that has the GetFoos method
// selectedFooName is the value of a DropDownList in the Page
// letting the user say how they want to see the animals
// its either one big group (Animal)
// or individual types (Tiger, Lion)
private void LoadFoos(string selectedFooName)
{
switch (selectedFooName)
{
case "Animal": // abstract base class for all other types
this.view.SetData(this.wrapper.GetFoos<Animal>();
case "Lion":
this.view.SetData(this.wrapper.GetFoos<Lion>();
break;
case "Tiger":
this.view.SetData(this.wrapper.GetFoos<Tiger>();
break;
case "Bear":
this.view.SetData(this.wrapper.GetFoos<Bear>();
break;
}
}
The View implementation (codebehind for an ASPX page)
public void SetData<T>(List<T> data)
{
// there is a multiview on the page that contains user controls with
// grid layouts for the different types
// there is a control for the common type of "Animal"
// and other controls for Tiger, Bear, etc
// the controls contain a 3rd party grid of pain
// and the grids' binding event handlers cast the data item
// for the row and do some stuff with it specific to that type
}
Our first pass was going to be at least using the Type in the switch statement, or adding an enum.
I played around with using the Strategy Pattern but had to stop when I got to the loading factory returning the List again and realizing I didn't have the type.
It's difficult without seeing the code calling GetFoos()... If you can show more code describing how this is being called, we can suggest how to refactor that.
It sounds like the solution is to make your calling routine a generic routine as well - so that it can avoid the "switch" around the 20 types by just using a single generic type, specified as needed. However, this may not be feasable, but again, without code, it's difficult to know...
That being said, you can refactor GetFoos to be much simpler:
public List<T> GetFoos<T>()
{
return Foos.OfType<T>().ToList();
}
Edit: As Eric Lippert points out, the above code returns any type that is a type of T, but also subclasses of T. Although this is most likely the behavior that would actually be desired, it is different than the original code. If this is not desirable for some reason, you could, instead, use:
public List<T> GetFoos<T>()
{
Type type = typeof(T);
return Foos.Where(item => item.GetType() == type).ToList();
}
This will have the same behavior as the original code.
Something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace SO_2480770 {
interface IFoo {}
class MyBase : IFoo {}
class Bar : MyBase {}
class Program {
IEnumerable<IFoo> Foos { get; set; }
static void Main(string[] args) {
List<MyBase> bases = new List<MyBase>() { new MyBase(), new MyBase() };
List<Bar> bars = new List<Bar>() { new Bar(), new Bar() };
Program p = new Program();
p.Foos = bases.Concat(bars);
var barsFromFoos = p.GetFoos<Bar>();
var basesFromFoos = p.GetFoos<MyBase>();
Debug.Assert(barsFromFoos.SequenceEqual(bars));
Debug.Assert(basesFromFoos.SequenceEqual(bases.Concat(bars)));
Debug.Assert(!barsFromFoos.SequenceEqual(bases));
Console.ReadLine();
}
public List<T> GetFoos<T>() where T : IFoo {
return Foos.OfType<T>().ToList();
}
}
}
To get rid of big switch statements, you either have to push the generics futher up. I.E. make the method that has the switch statement take a generic type parameter, and keep going until you can't go any futher, if you have to, up the calling chain. When that gets too difficult, think about design patterns such as abstract factory, factory, template methods etc.... It depends on how complex the calling code is.

Categories