I've made a generic class that saves and queries objects from a flat file. I keep having to change the method arguments to objects so I can cast them and I'm wondering if I'm going about this the right way...
'T' will always inherit 'FlatFileRecord'
This does not compile:
public class FlatFile<T>
{
public void Save(T record)
{
FlatFileRecord castedRecord = (FlatFileRecord)record;
castedRecord.RecordNumber...
}
}
This compiles but seems to defeat the whole point of a strongly typed generic class:
public class FlatFile<T>
{
public void Save(object record)
{
FlatFileRecord castedRecord = (FlatFileRecord)record;
castedRecord.RecordNumber...
}
}
If T is always going to be derived from FlatFileRecord, then constrain it that way:
public class FlatFile<T> where T : FlatFileRecord
{
public void Save(T record)
{
FlatFileRecord flatRecord = record;
flatRecord.RecordNumber...
}
}
If you need to make do without the constraint for some reason, you can cast to object and then back down again:
public class FlatFile<T>
{
public void Save(T record)
{
FlatFileRecord flatRecord = (FlatFileRecord)(object)record;
flatRecord.RecordNumber...
}
}
Related
I want to implement an interface in C# and there is a function called Testfunction.
For example:
public interface Test
{
void Testfunction(type filter);
}
But I want to make all the classes inherit this interface can implement this Testfunction with all different type of parameters, is it possible?
You can try using generics, e.g.:
public interface ITest<T>
{
void TestFunction(T filter);
}
then you can put:
// Here filter is of type int
public class MyTestInt : ITest<int> {
public void TestFunction(int filter) {
...
}
}
// And here filter is of type string
public class MyTestString : ITest<string> {
public void TestFunction(string filter) {
...
}
}
etc.
Yes, with Generics.
public interface Test<T>
{
void TestFunction(T filter);
}
Implementers would then do
public class Foo : Test<Bar>
{
public void TestFunction(Bar filter)
{
// ...
}
}
You can even add constraints to your generic parameter (T), as documented here, for example you could restrict it so that any type used as a type parameter must implement another specific interface, and a bunch more stuff
I'm looking for a delegate that encapsulates a method that return no value and take one parameter, like Action< T > does, but unfortunately that delegate does not match with method taking a child type as parameter...
That's what I'm trying to do:
public class BaseType
{
public BaseType()
{
}
}
public class ChildType : BaseType
{
public ChildType()
{
}
}
public class Test
{
public delegate void CallBackHandler(BaseType p);
public Test()
{
CallBackHandler clbk1 = callBackA;
CallBackHandler clbk2 = callBackB; //That line does not compile
//->'No overload for 'callBackB' matches delegate 'Test.CallBackHandler'
}
private void callBackA(BaseType p)
{
}
private void callBackB(ChildType p)
{
}
}
I read about covariance, contravariance, etc... I know it deals with the herited type casting but I'm a little bit confused about all of this...
Which delegate should I use to make my code work ?
This is the classic type safety problem that strong typing was created to solve.
Here's an example
abstract class Vehicle
{
public virtual void MethodSlot1_StartEngine() { }
public virtual void MethodSlot2_StopEngine() { }
}
class Car : Vehicle
{
public virtual void MethodSlot3_OpenGasTank() { }
}
class NuclearSubmarine : Vehicle
{
public virtual void MethodSlot3_FireAllNuclearMissiles() { }
}
class VehicleUser
{
public delegate void OpenGasTankMethod(Car car);
public void OpenGasTank(Vehicle vehicle, OpenGasTankMethod method)
{
//it's stopping you here from firing all nuclear weapons
//by mistaking your car's gas tank for the armageddon switch
method(vehicle);
}
}
When the compiler emits a virtual method call it just compiles an index into a lookup table. If you could pass in a NuclearSubmarine where a Car is required merely because they are both Vehicles, then you could think you are calling Car methods (like opening your gas tank) when in fact you are just making the Fallout series of games a reality.
In response to your comment, this should get you started:
class Blah
{
private List<Action<object>> _handlers = new List<Action<object>>();
public void AddListener<T>(Action<T> handler)
{
//graceful type checking code goes in here somewhere
_handlers.Add(o => handler((T) o));
}
void RaiseEvent(object eventArgs)
{
foreach (var handler in _handlers) handler(eventArgs);
}
}
You can't do this since it is not safe. If it were allowed you could do:
class OtherChild : BaseType { }
CallBackHandler clbk2 = callBackB;
clbk2(new OtherChild());
and pass an instance of OtherChild to a delegate which requires an instance of ChildType. Note that the following is safe and compiles:
public delegate void CallBackHandler(ChildType p);
CallBackHandler clbk1 = callBackA;
CallBackHandler clbk2 = callBackB;
Declare the delegate as
public delegate void CallBackHandler(ChildType p)
If the handler could accept and should act on instances of BaseType, what would happen if you passed in an instance of a new class NewChildType? Nobody knows, which is the reason why you can't here.
I need to create two partial interfaces. One with a constraint and the other without, like:
public partial interface IMyCuteInterface<T> where T : IEnumerable
{
void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}
public partial interface IMyCuteInterface<T>
{
void DoSomeStuff();
void DoSomeStuff2();
}
This is the implementation:
public class CuteInterfaceImplementation<T> : IMyCuteInterface<T>
{
private readonly T _element;
public CuteInterfaceImplementation(T element)
{
_element = element;
}
public void DoSomethingOnlyPossibleIfGenericIsIEnumerable(){}
public void DoSomeStuff(){}
public void DoSomeStuff2() { }
}
This is a static method to get this more dynamically:
public class CuteInterfaceImplementationBase
{
public static IMyCuteInterface<T> From<T>(T t)
{
return new CuteInterfaceImplementation<T>(t);
}
}
and this is the way I want to call it:
public static void Main(string[] args)
{
var mci = CuteInterfaceImplementationBase.From(args);
}
So, C# wants me to add the generic type constraint I added in the first interface to my CuteInterfaceImplementationBase.From<T> and my CuteInterfaceImplementation<T>-class.
What I want to achieve is: args could either be e.g. from type List<T> or from type int or something else. My target is, if args is from type IEnumerable<T> I want to add more functions (via the interface with the constraint) to CuteInterfaceImplementation-instance.
example:
if args is from type IEnumerable, this instance from CuteInterfaceImplementation has methods:
void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
void DoSomeStuff();
void DoSomeStuff2();
if args is from type Foo or int (or any type that doesn't implement IEnumerable) I can use methods:
void DoSomeStuff();
void DoSomeStuff2();
means, DoSomethingOnlyPossibleIfGenericIsIEnumerable is not available.
But it seems, this is not possible, since I need to add the constraint to my implemented class. Any idea how to do this?
Not sure that this approach good idea, it violates the "I" in SOLID - interface
segregation
no client should be forced to depend on methods it does not use
You're using partial to split up two fundamentally different interfaces, you should have 2 different interface because they are different.
To answer your question:
If you're committed to a similar approach on the conditions of T, you could split the interfaces, move the "common logic" (which both interfaces use) to a base class and use the From<T> method to conditionally choose which implementation to create.
Something like this:
public partial interface IMyCuteInterface_WITHEnumerable<T> : IMyCuteInterface<T> where T : IEnumerable
{
void DoSomethingOnlyPossibleIfGenericIsIEnumerable();
}
public partial interface IMyCuteInterface<T>
{
void DoSomeStuff();
void DoSomeStuff2();
}
And then the implementations:
public class CuteInterfaceImplementation<T> : CuteInterfaceImplementation_COMMON<T>
{
public CuteInterfaceImplementation(T element) : base(element)
{
}
}
public class CuteInterfaceImplementation_COMMON<T> : IMyCuteInterface<T>
{
private readonly T _element;
public CuteInterfaceImplementation_COMMON(T element)
{
_element = element;
}
public void DoSomeStuff() { }
public void DoSomeStuff2() { }
}
public class CuteInterfaceImplementation_WITHEnumerable<T> : CuteInterfaceImplementation_COMMON<T>, IMyCuteInterface_WITHEnumerable<T> where T : IEnumerable
{
private readonly T _element;
public CuteInterfaceImplementation_WITHEnumerable(T element) : base(element)
{
_element = element;
}
public void DoSomethingOnlyPossibleIfGenericIsIEnumerable() { }
}
Finally your "static helper", which decides on the class to instantiate:
Unfortunately it's not possible in C# to conditionally instantiate the different classes because one expects T to be IEnumerable while the other doesn't. You can get around that using dynamic
public class CuteInterfaceImplementation_HELPER
{
public static IMyCuteInterface<T> From<T>(T t)
{
if (t is IEnumerable)
{
dynamic dyn = t;
return FromEnumerable(dyn);
}
else
{
return new CuteInterfaceImplementation<T>(t);
}
}
public static IMyCuteInterface<T> FromEnumerable<T>(T t) where T: IEnumerable
{
return new CuteInterfaceImplementation_WITHEnumerable<T>(t);
}
}
I wanted to create an abstract class with an abstract method that takes a generic type. My implementing class method will do something with that type but because its generic I dont have access to the properties of the real object thats passed in the method. If I try casting then it won't compile as you cant cast back to a T type. An example of my meaning.
public abstract class TestAbstractClass
{
public abstract void Method<T>(ref IQueryable<T> query);
}
public class TestA:TestAbstractClass
{
// T in this class is an object with a property called Forename
public override void Method<T>(ref IQueryable<T> query)
{
query = query.OrderBy(o=>o.Forename); // unaware of property forename
query = ((IQueryable<Person>)query).OrderBy(o=>o.Forename); // breaks because of casting
}
}
public class TestB:TestAbstractClass
{
// T in this class is an object with a property called HandSize
public override void Method<T>(ref IQueryable<T> query)
{
query = query.OrderBy(o=>o.HandSize); // unaware of property
query = ((IQueryable<Glove>)query).OrderBy(o=>o.HandSize); // breaks because of casting
}
}
I hope this makes sense and I'm not being stupid.
Cheers
A solution could be:
public abstract class TestAbstractClass<T>
{
protected virtual void Method(ref IQueryable<T> query)
{
}
}
class TestA : TestAbstractClass<Person>
{
protected override void Method(ref IQueryable<Person> query)
{
var q = query.OrderBy(p => p.Forename);
}
}
That code is fragile as it's easy to break it. No one can tell by looking at that method that the sub class only allows one type of entity.
There is a principle called Liskovs Substitution Principle which says that any method that takes a base class should be able to work with any kind of subclass. In this case the <T> specifier could be compared to object.
I think that you meant to do this:
public abstract class TestAbstractClass<T>
{
public abstract void Method(ref IQueryable<T> query);
}
public class TestA : TestAbstractClass<Person>
{
// T in this class is an object with a property called Forename
public override void Method(ref IQueryable<T> query)
{
query = query.OrderBy(o=>o.Forename); // unaware of property forename
}
}
public class TestB:TestAbstractClass<Glove>
{
// T in this class is an object with a property called HandSize
public override void Method(ref IQueryable<T> query)
{
query = query.OrderBy(o=>o.HandSize); // unaware of property
}
}
The difference is that you specify that the entire class can only work with one type of entity which allows you to get intellisense etc.
I have a problem with a typed method in C#.
I want to invoke a inherited method of an object.
This method invokes a static method with "this" as parameter.
The parameter of the static method is generic.
I now want the generic type of this parameter to be the type of the first object.
But the parameter has always the type of the abstract class.
Here is the example:
abstract class AbstractClass
{
bool update()
{
Connection.Update(this);
}
}
class Entity : AbstractClass
{
}
class Connection
{
public static void Update<T>(T obj)
{
someMethod<T>()
}
}
If I try to do:
Entity foo = new Entity();
foo.update();
Connection.Update will look in the Debugger like this:
public static void Update<AbstractClass>(AbstractClass obj)
{
someMethod<AbstractClass>()
}
But I want this:
public static void Update<Entity>(Entity obj)
{
someMethod<Entity>()
}
Is there any possibility to something like
someMethod<typeof(obj)>()
or anything else to solve my problem?
You can declare the base class as a generic one, here is the example:
abstract class AbstractClass<T>
{
bool update()
{
Connection.Update<T>(this as T);
}
}
class Entity : AbstractClass<Entity>
{
}
class Connection
{
public static void Update<T>(T obj)
{
someMethod<T>()
}
}
Compiler tries to infer the type of T parameter, in the base class it does not have information to infer Entity type. So you should provide information of the child type while you want to call the Update function.#Alexandr answer is a good one just an improvement adding type constraint to T type parameter to restrict it be a child of AbstractClass
abstract class AbstractClass<T>
where T: AbstractClass<T> //restrict T as a child of AbstractClass<T>
{
bool update()
{
Connection.Update<T>(this as T);
}
}
class Entity : AbstractClass<Entity>
{
}
class Connection
{
public static void Update<T>(T obj)
{
someMethod<T>()
}
}
If you want a quick fix then cast this to dynamic which will delay the type evaluation to runtime. However, consider using the visitor pattern.
public bool update()
{
Connection.Update((dynamic)this);
return true;
}
Visitor pattern:
public interface IEntityVisitor
{
void Visit(EntityBase entity);
void Visit(Entity entity);
}
public interface IEntity
{
void Accept(IEntityVisitor visitor);
}
public abstract class EntityBase : IEntity
{
public virtual void Accept(IEntityVisitor visitor)
{
visitor.Visit(this);
}
}
public class Entity : EntityBase
{
public override void Accept(IEntityVisitor visitor)
{
visitor.Visit(this);
}
}
var genericType = typeof(Connection<>);
var specificType = genericType.MakeGenericType(typeof(Entity));
var conn = Activator.CreateInstance(specificType);
Any thing like someMethod<typeof(obj)>() does not exist as it would break the type safety of C#, because the compiler cannot know the runtime type of a parameter. However, you can get the true type object by invoking obj.GetType(). You can use this type object to call methods dynamically using Reflection.
One solution on this:
abstract class AbstractClass
{
bool update<T>()
{
Connection.Update(T);
}
}
then,
Entity foo = new Entity();
foo.update<Entity>();