I have problem as above. My code:
public abstract class BaseFactory<T> where T: class
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
and my question is how can I call
BaseFactory.UpdateDataBase_static();
instead of:
BaseFactory<SomeClass>.UpdateDataBase_static();
Any ideas?
You can't, because there is no such method. The closest is to have a non-generic base that the generic class inherits from. Then you can have a method there that doesn't depend on the parameterising type.
To call BaseFactory.UpdateDataBase_static(); you need a class BaseFactory. Inherite the generic BaseFactory<T> from it.
public abstract class BaseFactory
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
public abstract class BaseFactory<T>:BaseFactory where T: class
{
....
}
You don't.
You always need to supply the generic type arguments when accessing a class, even though you aren't using that type argument in your method. Since you don't actually use the generic type in the method it means you could move that method out of that class, and into one that isn't generic, but for as long as it's in that class you'll need to supply the generic argument.
It's not possible to do exactly what you're asking, but since the method doesn't use T at all, you can just use BaseFactory<object>.UpdateDataBase_static(); without specifying any particular class.
But as an editorial comment, in general a method in a generic class that never uses the generic parameter probably shouldn't be there.
Related
Here's the situation. I have a class and a derived class
public class MyClass
{ }
public class MyDerivedClass : MyClass
{ }
And also I have a method (in an external class) which takes an instance of MyClass as a parameter:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{ }
}
How can I restrict DoSomething method to accept instances of MyClass only, but not instances of MyDerivedClass?
If that's what you want then you would need to check in code yourself that if it is a Derived type through Exception to tell the calling code that Derived type objects are not allowed for this method:
public class AnotherClass {
public void DoSomething(MyClass myClass)
{
if(myClass.GetType() != typeof(MyClass))
{
throw new Exception("Derived objects not allowed");
}
}
}
What are you trying to do here is more related to an Invariance problem that is pretty common on all programming languages.
Means that you can use only the type originally specified; so an
invariant generic type parameter is neither covariant nor
contravariant. You cannot assign an instance of IEnumerable
(IEnumerable) to a variable of type
IEnumerable or vice versa.
Here is the reference for you https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
My advice, try to change the implementation and put all the methods into an interface, that should be more clear
class Root: Interface
{
...implementation of your common methods
}
class Derived: Interface
{
...implementation of your common methods
//this should just
public void DoSomething(MyClass myClass)
}
If you don't want to use the above approach then use the "as" operator to treat the parameter that you are passing as MyRootClass, var a = parameter as MyRootClass. If a is null then you are not passing the correct value to the method, or check for the type directly.
If would recommend that you read this topics:
http://amapplease.blogspot.com/2009/04/invariance-covariance-contravariance.html
https://stackoverflow.com/a/13107168/819153
https://blogs.msdn.microsoft.com/ericlippert/2009/03/19/representation-and-identity/
Hope this helps
Basically, I want to write a wrapper for all ICollection<> types. Lets call it DelayedAddCollection. It should take any ICollection as its .
Furthermore, I need access to that ICollection type's generic type as the Add method needs to restrict its parameter to that type.
The syntax I would imagine would look something like this...
public DelayedAddConnection<T>: where T:ICollection<U> {
....
public void Add(U element){
...
}
}
What is the real correct syntax to do this?
You need to add another generic type parameter:
public class DelayedAddConnection<T, U> where T : ICollection<U>
{
}
So, for future reference the final, cleanest version of this idea I implemented thanks to all the suggestions and comments was this:
public class DelayedUpdateCollection<U>: ICollection<U>
{
ICollection<U> collection;
public DelayedUpdateCollection(ICollection<U> coll){
collection = coll;
}
...
public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.
I'm working on a small class library at work, and it naturally involves using generics for this task. But there is this thing that I don't really understand with generics:
Why would I need to use generic type parameters, and then constrain the the type parameter to a specific base class or interface.
Here's an example to what I mean:
public class MyGenericClass<T> where T : SomeBaseClass
{
private T data;
}
And here's the implementation without generics
public class MyClass
{
private SomeBaseClass data;
}
Are these two definitions the same (if yes, then i don't see the advatage of using generics here)?
If not, what do we benefit from using generics here?
As with almost all uses of generics, the benefit comes to the consumer. Constraining the type gives you the same advantages that you get by strongly typing your parameter (or you can do other things like ensure that there's a public parameterless constructor or ensure that it's either a value or reference type) while still retaining the niceties of generics for the consumer of your class or function.
Using generics also, for example, allows you to obtain the actual type that was specified, if that's of any particular value.
This example is a little contrived, but look at this:
public class BaseClass
{
public void FunctionYouNeed();
}
public class Derived : BaseClass
{
public void OtherFunction();
}
public class MyGenericClass<T> where T: BaseClass
{
public MyGenericClass(T wrappedValue)
{
WrappedValue = wrappedValue;
}
public T WrappedValue { get; set; }
public void Foo()
{
WrappedValue.FunctionYouNeed();
}
}
...
var MyGenericClass bar = new MyGenericClass<Derived>(new Derived());
bar.Foo();
bar.WrappedValue.OtherFunction();
The difference is that the former defines the new class as a specific type; the latter simply defines a plain class with a field of that type.
It's all about type safety. Using generics you can return a concrete type (T) instead of some base type which defines the API you need in your generic class. Therefore, the caller of your method won't have to cast the result to the concrete type (which is an error-prone operation).
The main difference is in usage. In the first case, the usage can have:
MyGenericClass<SomeDerivedClass> Variable
Variable.data.SomeDerivedProperty = X
And so that when you use that class, you can still access anything from SomeDerivedClass without casting back to it.
The second example will not allow this.
MyClass.data = SomeDerivedClassInstance
MyClass.data.SomeDerivedProperty = X //Compile Error
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww
You will have to cast back up to the SomeDerivedClass (which is unsafe) to use something specific to the derived class.
I don't think that there is a huge amount of difference except that the generic version is constraining your Class, whereas the second is just a constraint on a member of the class. If you added more members and methods to your first Class, you would have the same constraint in place.
I have something like this:
abstract class BaseClass<T>
{
protected BaseClass(){}
}
class Class1 : BaseClass<Class1>
{
public static Class1 Instance = new Class1();
private Class1(){}
}
class Class2 : BaseClass<Class2>
{
public static Class2 Instance = new Class2();
private Class2(){}
}
...
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>
{
switch(z)
{
case 1:
return Class1.Instance;
case 2:
return Class2.Instance;
}
}
That is very important that those classes cannot be instantiated since their construstors are private so we cannot do like
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>, new()
How can I use abstract class as return type ?? I just can not work this out. Would appreciate for any assisstance here.
It sounds to me like you can't really have the method be generic. For instance, what would happen if I called:
BaseClass<Class1> foo = Method<Class1>(2);
You need a single point of truth - either the type argument, or the normal argument. You can make it the method argument by having a non-generic base class (either by making the existing base class non-generic, or introducing a non-generic base class to that). Change the return type of Method to this non-generic base class.
abstract class BaseClass<T>
{
public abstract T Instance { get; }
protected BaseClass(){}
}
maybe? You can't inherit static stuff I believe...
On a closer look... I don't think what you are trying to do is even possible... what are you trying to do anyways?
A type constraint is a type constraint. You are trying to change the type constraint in the method kind of. which obviously doesn't work, and shouldn't work. I think you need to think of a different way of attacking your problem. Whatever it is...
Take a look at the factory pattern. Your factory can have a method on it to get the instance. The first time it's called, it creates the instance. On subsequent calls, it can return the already-created instance.