i saw some c# asp.net source code written as below:
public class EntityInstanceContext<TEntityType> : EntityInstanceContext
{
/// <summary>
/// Initializes a new instance of the <see cref="EntityInstanceContext{TEntityType}"/> class.
/// </summary>
public EntityInstanceContext()
: base()
{
}
can anyone help me to understand why the generic type is subclassing from non-generic one? and what is benifit of designing in that way?
The .NET TypeSystem is a very powerful one.
Imagine the following scenario. I'm writing a class called MyTuple which is a poorly coded clone of the BCL Tuple class:
public class MyTuple<T1, T2> {
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public MyTuple(T1 item1, T2 item2) {
this.Item1 = item1;
this.Item2 = item2;
}
}
And then I realize I want to make a factory kind of method for that type
so that I can successfully hook into the type inference system and not specify T1 and T2 when I don't have to like so:
new MyTuple<int, string>(123, "test"); // which is also a bit redundant
So I'm writing the method I was talking about in a class, let's call the class Factory:
public class Factory {
public static MyTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) {
return new MyTuple<T1, T2>(item1, item2);
}
}
That way, I'm happier when writing:
var tuple = Factory.Create(123, "test"); // and tuple is inferred to be of <int, string>
Now what would happen if I renamed Factory to MyTuple:
public class MyTuple {
public static MyTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) {
return new MyTuple<T1, T2>(item1, item2);
}
}
In short: nothing bad
It is simply the case that I now have 2 completely distinct types:
MyTuple (nongeneric)
MyTuple < T1, T2 >
They have nothing in common, they are different types.
And am I allowed to say that MyTuple<T1, T2> just happens to extend MyTuple ?
Well, as long as MyTuple is neither static nor sealed, yeah, sure !
public class MyTuple { ... }
public class MyTuple<T1, T2> : MyTuple { ... }
So in your case it's nothing more that Mammal extending Animal or ... Tiger extending Mammal.
It's not like Mammal of a weirder sort extending Mammal of a good ol' classical sort.
Related
To define a generic class:
public class TParent<T1, T2> { }
public class ChildManager<T1, T2, T3> where T3 : TParent<T1 , T2> { }
public class Child : TParent<int , double> { }
The class Child is an avaliable T3 type for ChildManager , but the class definiton of ChildManager is too long.
The T3 is derived from Tparent , and the T1,T2 has been already defined in TParent.
So, can the definiton be like such code?
public class ChildManager<T3> where T3:TParent<classtype,classtype> { }
However,such code is an error.
I'm trying to define an interface IScheduler that takes an T1 and returns a T2, and also has a type argument for an IJob<T1,T2> so that it knows what job to create. I'd like to call it as so:
public class SomeJob : IJob<string, int>
// preferred way to use the method
int result = scheduler.Schedule<SomeJob>("some_param");
and have the compiler infer that T1 is a string and T2 is an int. This is how I've tried defining the interface
public interface IScheduler
{
T2 Schedule<TJob, T1, T2>(T1 args) where TJob: IJob<T1, T2>;
}
Unfortunately, the compiler complains:
Using the generic method 'Schedule<TJob,T1,T2>(T1)' requires 3 type arguments
The type 'SomeJob' must be convertible to 'Job<T1, T2>' in order to use it as parameter 'TJob` in the generic method 'T2 IScheduler.Schedule<TJob,T1,T2>(T1)'
What I'd really like to do is this:
public interface IScheduler
{
T2 Schedule<TJob>(T1 args) where TJob: IJob<T1, T2>;
}
It isn't quite possible to get the syntax that you're looking for, but here are some things that would work:
int result = scheduler.Schedule(new SomeJob(), "some_param");
// using this
public interface IScheduler
{
T2 Schedule<T1, T2>(IJob<T1, T2> job, T1 args);
}
Or:
int result = scheduler.ForJob<SomeJob>.Schedule("some_param");
// using this
public interface IScheduler
{
IJobScheduler<TJob> ForJob<TJob>();
}
public interface IJobScheduler<out TJob> { }
public static class Extensions
{
public static T2 Schedule<T1, T2>(this IJobScheduler<IJob<T1, T2>> job, T1 args)
{
...
}
}
Or if you can get rid of the return argument, you can access the strongly typed type of TJob in the Schedule method:
scheduler.ForJob<JobWithNoReturn>().Schedule("some_param");
// using the stuff from #2 and also this
public static class Extensions
{
...
public static void Schedule<TJob, T1>(this IJobScheduler<TJob> job, T1 args)
where TJob : IJob<T1>
{
...
}
}
I am trying to pass multiple generic interfaces as parameters to the constructor of one of my classes.
The following code does not compile:
public interface IPosterGenerator<T>
{
IQueryable<T> GetPosters();
}
public class Pinboard
{
public Pinboard(IPosterGenerator<A> firstPosterGenerator, IPosterGenerator<B> secondPosterGenerator, IPosterGenerator<B> thirdPosterGenerator)
{
}
}
I have about a hundred different types of poster generators. They all inherit from the IPosterGenerator interface. When I instantiate a new Pinboard, I need to pass three IPosterGenerators to the pinboard's constructor. However, every of these three IPosterGenerators will be of a different type. That's why I came up with this silly A, B and C.
Can this be done at all?
It sounds like you probably want to make Pinboard generic:
public class Pinboard<T1, T2, T3>
{
public Pinboard(IPosterGenerator<T1> generator1,
IPosterGenerator<T2> generator2,
IPosterGenerator<T3> generator3)
{
...
}
}
To make it easier to call, you can also create a non-generic class with a generic method:
public static class Pinboard
{
public static Pinboard<T1, T2, T3> Create(IPosterGenerator<T1> generator1,
IPosterGenerator<T2> generator2,
IPosterGenerator<T3> generator3)
{
return new Pinboard<T1, T2, T3>(generator1, generator2, generator3);
}
}
Then if you've already got the generators, you can just call:
// Or whatever...
var board = Pinboard.Create(bigGenerator, smallGenerator, mediumGenerator);
You'll have to have your class declared generic with A, B & C as well. Something like this:
public class Pinboard<A,B,C> {
public Pinboard(IPosterGenerator<A> firstPosterGenerator,
IPosterGenerator<B> secondPosterGenerator,
IPosterGenerator<C> thirdPosterGenerator) {
}
}
Sorry again for not being precise enough in my original question. Here is what I found to be ok for me (and flexible enough for my needs):
public interface IPosterGenerator
{
}
public interface IPosterGenerator<T> : IPosterGenerator
{
IQueryable<T> GetPosters();
}
public class Pinboard
{
public Pinboard(List<IPosterGenerator> generators)
{
}
}
Thanks again for all your support, guys!
Similiar to this question: How can I require a method argument to implement multiple interfaces?
I want a method argument to implement several interfaces.
The interfaces shall be combinable in arbitrary fashion and I don't want to create an interface for each valid combination.
Think of a file. It can be:
readable => IReadable
writeable => IWriteable
an archive => IArchive
automatically generated => IGenerated
...
If I want to express that an argument needs to be an writable, generated archive I don't want to generate IWritableGeneratedArchive since there are too combinations and I want to use it with some existing classes I cannot modify.
Pseudocode:
void WriteTo( IWritable + IGenerated + IArchive file)
{
//...
}
The solution I found here: How can I require a method argument to implement multiple interfaces? adjusted for C#.
Credits go to Michael Myers
internal interface IF1
{
void M1();
}
internal interface IF2
{
void M2();
}
internal class ClassImplementingIF1IF2 : IF1, IF2
{
public void M1()
{
throw new NotImplementedException();
}
public void M2()
{
throw new NotImplementedException();
}
}
internal static class Test
{
public static void doIT<T>(T t) where T:IF1,IF2
{
t.M1();
t.M2();
}
public static void test()
{
var c = new ClassImplementingIF1IF2();
doIT(c);
}
}
A generic + constraint perhaps?
void WriteTo<T>( T file) where T : IWritable,IGenerated,IArchive
{
//...
}
Use generic constraints:
void WriteTo<T>(T file) where T: IWritable, IGenerated, IArchive
{
//...
}
See Constraints on Type Parameters (C# Programming Guide)
I don't want to generate IWritableGeneratedArchive since there are too combinations
How are there too many combinations? Whatever number of potential combinations there are, you only need to make a combined interface for the ones you actually use as a method parameter, and at that point you're writing it all out anyway. In other words, it's actually not that much more work.
I want to use it with some existing classes I cannot modify.
An IWritableGeneratedArchive type can be passed to something that only wants an IArchive or IWritable. This would still work with anything else you already have.
But since you've already decided against this and it looks like you already invested a lot in this architecture, I wonder if you've seen Code Contracts. They look like they might do what you need.
This solution tries to incorporate supercat's idea with storing such "multi interface" objects.
I've done this by storing them in a Holder class that exposes the stated interfaces of the object.
Holder objects can be stored and are the expected argument. The downside is that you have to create the Holder first and that the order of Holder's type arguments matters.
On the plus side though you can also dynamically create Holders and of course store "multi interface" objects.
It would have been nice to enable the holder.Get<T>() methods (nicer than holder.t1) but it won't compile.
Maybe someone has an idea how to fix it? I think it needs to add the constraint T1 is not T2 and vice versa. This seams to be related to C# generic does *not* implement something and they didn't find a solution.
internal interface IF1
{
void M1();
}
internal interface IF1_extension : IF1
{
}
internal interface IF2
{
void M2();
}
internal class ClassImplementingIF1IF2 : IF1_extension, IF2
{
public void M1()
{
throw new NotImplementedException();
}
public void M2()
{
throw new NotImplementedException();
}
}
internal interface Getter<T> where T : class
{
T Get();
}
internal class Holder<T1, T2> //: Getter<T1>, Getter<T2> // not possible since T1 and T2 may be the same => won't compile!
where T1 : class
where T2 : class
{
private Holder(T1 t1, T2 t2)
{
Debug.Assert(t1 != null, "Argument is no " + typeof(T1).Name);
Debug.Assert(t2 != null, "Argument is no " + typeof(T2).Name);
this.t1 = t1;
this.t2 = t2;
}
public static Holder<T1, T2> CreateFrom<T>(T t) where T : T1, T2
{
return new Holder<T1, T2>(t, t);
}
public static Holder<T1, T2> CreateDynamicallyFrom(object t)
{
return new Holder<T1, T2>(t as T1, t as T2);
}
public readonly T1 t1;
public readonly T2 t2;
//T1 Getter<T1>.Get()
//{
// return t1;
//}
//T2 Getter<T2>.Get()
//{
// return t2;
//}
}
internal class Holder<T1, T2, T3> // Holder<T1,T2,T3,T4> etc. are defined in a similar way
where T1 : class
where T2 : class
where T3 : class
{
private Holder(T1 t1, T2 t2, T3 t3)
{
Debug.Assert(t1 != null, "Argument is no " + typeof(T1).Name);
Debug.Assert(t2 != null, "Argument is no " + typeof(T2).Name);
Debug.Assert(t3 != null, "Argument is no " + typeof(T3).Name);
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
public static Holder<T1, T2,T3> CreateFrom<T>(T t) where T : T1, T2, T3
{
return new Holder<T1, T2, T3>(t, t, t);
}
public static Holder<T1, T2, T3> CreateDynamicallyFrom(object t)
{
return new Holder<T1, T2, T3>(t as T1, t as T2, t as T3);
}
public readonly T1 t1;
public readonly T2 t2;
public readonly T3 t3;
}
internal static class Test
{
public static void doIt<T>(T t) where T : IF1, IF2
{
t.M1();
t.M2();
}
public static void doIt(Holder<IF1, IF2> t) // Interfaces should be mentioned in alpahbetical order since Holder<IF1,IF2> != Holder<IF2,IF1>
{
t.t1.M1();
t.t2.M2();
}
public static void doIt_extended<T1, T2>(Holder<T1, T2> t) // handles conversions from Holder<T1,T2> to Holder<T1 or base of T1, T2 or base of T2>
where T1 : class, IF1
where T2 : class, IF2
{
t.t1.M1();
t.t2.M2();
}
public static void test()
{
var c = new ClassImplementingIF1IF2();
doIt(c);
var c_holder = Holder<IF1, IF2>.CreateFrom(c);
doIt(c_holder);
var another_c_holder = Holder<IF1_extension, IF2>.CreateFrom(c);
doIt_extended(another_c_holder);
object diguised_c = c;
var disguised_c_holder = Holder<IF1, IF2>.CreateDynamicallyFrom(diguised_c);
doIt(disguised_c_holder);
}
}
Should this be possible using c# 4 and VS 2010? I am doing some processing on class(es) which implements generic interface(s), and after processing would like to convert the objects to a simpler interface so I can extract certain properties defined by common Interfaces.
interface IMyInterface
{
public Id { get; set; }
}
interface IFile<T1, T2> where T1 : IMyInterface where T2 : IMyInterface
{
Int64 prop1 { get; set; }
T1 t1 { get; set; }
T2 t2 { get; set; }
}
ClassA : IMyInterface
{
... Implement some properties plus interface
public Id { get; set; }
}
ClassB : IMyInterface
{
... Implement some properties plus interface
public Id { get; set; }
}
For example this class has ClassX and ClassY which I want to be certain types for processing/saving, but after that I only want to extract common properties like an ID which is common amongst all classes that Implement this generic Interface (other properties are not common in t1, t1)
ClassSomething : IFile<ClassA, ClassB>
{
... Implement properties plus interface
public ClassX t1
{ get {} set {} }
public ClassY t2
{ get {} set {} }
}
IList<IFile<TItem1, TItem2>> list = new List<IFile<TItem1, TItem2>>()
ClassA ca = new ClassA();
... Fill in the interface defined properties
... Fill the list with objects of ClassSomething
foreach (IFile<TItem1, TItem2> x in list)
{
// This fails
IFile<IMyInterface, IMyInterface> interfaceItem =
(IFile<IMyInterface, IMyInterface>)x;
}
The cast of x above (t1 and t2 properties specifically) to the simpler IMyInterface interface fails.
There are quite a few generic interface questions but I didn't see (or recognize?) any solutions.
The solution you are looking for is called variance (covariance and contravariance). However your IMyInterface cannot be made either covariant or contravariant in T1 and T2, because it has both public getters and public setters accepting T1 and T2:
interface IAnimal {}
class Dog : IAnimal { public void Bark () ; }
class Cat : IAnimal { public void Meow () ; }
var dogs = new FileImpl<Dog, Dog> () ;
dogs.t1 = new Dog () ;
var file = (IFile<IAnimal, IAnimal>) dogs ; // if this were OK...
file.t1 = new Cat () ; // this would have to work
dogs.t1.Bark () ; // oops, t1 is a cat now
Just to expand on Anton Tykhyy's answer,
Yes, you could achieve this with C# 4, provided that you are willing/able to make the following change to your IFile interface:
interface IFile<out T1, out T2> where T1 : IMyInterface where T2 : IMyInterface
{
Int64 prop1 { get; set; }
T1 t1 { get; }
T2 t2 { get; }
}
I've added the out keyword to the generic parameters, and I've removed the set; from the t1 and t2 properties.
Why just not access x.T1 and x.T2 and then cast both to IMyInterface?
foreach (IFile<TItem1, TItem2> x in list)
{
var t1 = x.T1 as IMyInterface;
var t2 = x.T2 as IMyInterface;
}
I think you're confusing the generic constraits with inheritance. The one has nothing to do with the other. The constraints on the generic interface are compiler instructions that tell the compiler that the generic arguments must meet a specific requirment. Logically, to us, that means that ClassSomething definitely has an implementation of IMyInterface. But that's us, the compiler doesn't translate those constraints to any kind of inheritence mapping, so it still only knows that it's an instance of ClassSomething which implements IFile<ClassA, ClassB>. So it won't let you directly cast that to IFile<IMyInterface, IMyInterface>.