I am new to C# and I am faced with a class with this structure:
public class SimpleGetter<TSubs> : GetterBase<TSubs>, ISubscriptionsSingleGetter<TSubs>
where TSubs : class, ISimpleSubscription, new()
{
UserSubscriptionsResponse<TSubs> ISubscriptionsSingleGetter<TSubs>.Get()
{
return ((ISubscriptionsSingleGetter<TSubs>)this).Get(null);
}
UserSubscriptionsResponse<TSubs> ISubscriptionsSingleGetter<TSubs>.Get(string userId)
{
return GetSubsResponse(userId);
}
}
I need to pass userID to the get() function (if possible), but I am confused on how to do that. I have tried to do some research on this but I do not even know what this way of defining a class is called. I come from objective c where things seem more straight forward.
I do not even know what this way of defining a class is called
This is a generic class.
public class SimpleGetter<TSubs> : GetterBase<TSubs>, ISubscriptionsSingleGetter<TSubs>
where TSubs : class, ISimpleSubscription, new()
which has one generic type parameter TSubs. This class inherits the GetterBase<TSubs> and implements the interface ISubscriptionsSingleGetter<TSubs>. Furthermore, the TSubs must be a reference type and must have a parameterless constructor, which implements the ISimpleSubscription interface.
public class FakeSubs : ISimpleSubscription
{
public FakeSubs()
{
}
// Here you have to implement ISimpleSubscription.
// You could also define any properties, methods etc.
}
// Now you could use your generic class as below:
var simpleGetter = new SimpleGetter<FakeSubs>();
Having created the above instance, you can call the Get method as Tewr, pointed out in his comment:
var response = ((ISubscriptionsSingleGetter<FakeSubs>)simpleGetter).Get(42);
Just to complement Christos' answer and help you understand the syntax a bit better, let's break the class definition term by term.
public - visible to all callers.
class - a reference type (i.e. not a struct).
SimpleGetter<TSubs> - the class name is SimpleGetter, and it is generic with respect to the parameter TSubs.
: GetterBase<TSubs> - it inherits from a base class which is itself generic with respect to the parameter TSubs.
, ISubscriptionsSingleGetter<TSubs> - and it also implements the generic interface ISubscriptionSingleGetter.
where TSubs: - there are some constraints on the type which the generic parameter TSubs must be of.
class - it must itself also be a reference type.
ISimpleSubscription - it must implement this (non-generic) interface.
new() - it must have a public parameterless constructor.
Related
I am certain that I simply do not know the name for what I am trying to do, otherwise my googling would be more successful. I currently only find results pertaining to interfaces with same named methods.
I have a few classes that inherit from a common base class and some implement an interface. I have methods accepting the base class or the interface as a parameter. I cannot compile since this causes ambiguity with the error
the call is ambiguous between the following methods or properties: DoThings(IQueryable<A>) and DoThings(IQueryable<B>)` on the call in ConcreteExecutionClass.
Furthermore, generics won't work because type constraints on generics do not make a unique method signature.
Is there a way (or an acceptable pattern) to force the execution to a specific method based on parameter types?
public abstract class A {
// some properties
}
public class ConcreteA : A {
// full implementation
}
public interface B {
// a property
}
public class ConcreteAB : A, B {
// full implementation
}
public abstract class ExecutionClass {
public IQueryable<A> DoThings(IQueryable<A> content){
return A.method().AsQueryable();
}
public IQueryable<B> DoThings(IQueryable<B> content){
return B.interfaceRequiredMethod().method().AsQueryable();
}
}
public class ConcreteExecutionClass : ExecutionClass {
public void Program(){
var objectList = new List<ConcreteAB>{/*....*/};
DoThings(objectList);
}
}
Each of the concrete classes has a class managing linq queries on lists of objects, which each call DoThings(). The goal is to keep the actual implementation of DoThings() transparent to the concrete classes.
I have attempted covariance in the interface, however have been unable to avoid inheriting A which forces down the first code path.
The code above is a simplification of the actual implementation. There are about 10 classes deriving solely from A and 4 deriving from A and B.
I simply created an abstract hierarchy where abstract A is the base and there are 2 abstract classes inheriting from it.
I'm working with generics in C#, and I feel like I have redundant information in my type specifications.
I have an interface named IParameterizedViewModel, which is generic on a parameter type. I also have another abstract class (android activity), which uses that kind of ViewModel.
public interface IParameterizedViewModel<TParameter> : IBaseViewModel
{
}
abstract class BaseActivity<TViewModel, TParameter> : BaseActivity<TViewModel>
where TViewModel : IParameterizedViewModel<TParameter>
{
// Somewhere in here, we use the TParameter type,
// so it's important to know the type.
}
You can see here that the BaseActivity has a generic IParameterizedViewModel type. I also have types which fill the generic slots for these two:
public interface IDetailsViewModel : IParameterizedViewModel<Details>
{
}
class DetailsActivity : BaseActivity<IDetailsViewModel, Details>
{
}
Now here's the thing: this last definition, DetailsActivity looks redundant as to the parameter type Details, since that type is also included in the IDetailsViewModel
Is there a way I could get away with removing the Details type, since it is already specified in the IDetailsViewModel type?
class DetailsActivity : BaseActivity<IDetailsViewModel>
{
}
I have three classes, one base class which takes a generic type that must be a subclass of an abstract class which in turn takes a generic type that must implement an interface.
For testing I have a form which will initiate the base class giving a subclass of the abstract class and an implementation of the interface. Here are my class declarations, and call to the base class constructor.
public class BaseClass<AC_IC> where AC_IC : AbstractClass<InterfaceClass>
public abstract class AbstractClass<IC> where IC: InterfaceClass
public interface InterfaceClass
public class ExtendsAbstractClass<II> : AbstractClass<InterfaceClass>
public class ImplementsInterface : InterfaceClass
vBC = new BaseClass<ExtendsAbstractClass<ImplementsInterface>>();
I believed I would be able to create instances of both of the inheriting/implementing classes from within the BaseClass and AbstractClass using the following calls (only one class will have parameters in the constructor)
(AC_IC) Activator.CreateInstance(typeof(AC_IC), new object[] { vParameter});
(II) Activator.CreateInstance(typeof(II));
EDIT: The above calls are within the BaseClass and AbstractClass and therefore do not know which classes I will use subsequently, so cannot be specified by class name, there may be many different pairs of classes for a range of implementations.
For both of these constructor calls I get the errors 'Cannot create an instance of an abstract class' & 'Cannot create an instance of an interface'. How can I let the compiler know that the classes that I am passing as the generic types are subclassess of the classes in the where clauses and so can be created.
Any ideas community???
The errors speak for themselves: You cannot create an instance of an abstract type.
You CAN cast the resulting type back to a base type, tho:
(AC_IC) Activator.CreateInstance(
typeof(BaseClass<ExtendsAbstractClass<ImplementsInterface>),
new object[] { vParameter});
EDIT:
public TFinal MakeMeA<TOuter,TInner,TInnermost,TFinal>(params object[] additionalCrap)
{
// figure out innermost type
var innermostType = typeof(TInner).MakeGenericType(typeof(TInnermost));
// work outwards
var nextLevel = typeof(TOuter).MakeGenericType(innermostType);
// figure out what the heck we're making
var returnType = typeof(TFinal).MakeGenericType(nextLevel);
// And make one of those
return (TFinal)Activator.CreateInstance(returnType, additionalCrap);
}
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.
Here is what I'm trying to do, not even sure if possible..
I'm creating BaseViewModel<T> and I want it to accept types inherited from Entity
Consider this code:
public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
{
public T MyEntity;
public SomeMethod()
{
MyEntity.SomeEntityProperty = SomeValue;
}
}
So, I want to say that my T inherited from Entity and therefore I KNOW that it will have SomeEntityProperty.
Is this possible?
Salvatore's answer is totally correct, I just wanted to describe the concept a little better.
What you need is a "generic type constraint"; to specify that the type used as T must conform to certain behaviors (such as being derived from an object or interface more derived than Object), thus increasing what you are allowed to do with that object without further casting (which is generally to be avoided in generics).
As Salvatore's answer shows, GTCs are defined using the "where" keyword:
public abstract class BaseViewModel<T> :
NotificationObject,
INavigationAware
where T : Entity;
{
...
This GTC basically states that any T must derive (however remotely) from Entity. This allows you to treat T as if it were an Entity (except for instantiation of new Ts; that requires an additional GTC), regardless of how more or less derived the actual generic parameter type is from Entity. You can call any method that appears on Entity, and get/set any field or property.
You can also specify that:
The type must be a class (where T:class), or alternately must be a ValueType (where T:struct). This either permits or prevents comparison and assignment of a T instance to null, which also allows or prevents use of the null-coalescing operator ??.
The type must have a parameterless constructor (where T:new()). This allows instantiations of Ts using the new keyword, by ensuring at compile-time that all types used as Ts have a constructor that takes no parameters.
public abstract class BaseViewModel<T> :
NotificationObject,
INavigationAware
where T : Entity
{
public T MyEntity;
public SomeMethod()
{
MyEntity.SomeEntityProperty = SomeValue;
}
}
Just use the where keyword:
public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
where T:Entity
{
...
Try using the where constraint:
public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
where T : Entity
{
public T MyEntity;
public SomeMethod()
{
MyEntity.SomeEntityProperty = SomeValue;
}
}