How to write a generic method and its default equivalent in C# - c#

I think this example is extremely simple and shows what I am trying to achieve:
public class A : A<object>
{
// public static A GetInstance() => new A();
// I can't do this, because cannot override static methods
}
public class A<T>
{
public static A<T> GetInstance() => new A<T>();
// public static A GetInstance() => new A();
// can't do this, because it says that the method is already defined
}
I basically want to be able to use the method GetInstance in two ways:
Specifying the type T: A<T>.GetInstance() or A.GetInstance<T>() (doesn't matter which one) - which should return the type A<T>
Without specifying this type: A.GetInstance() - which should return the type A.
How can I achieve this?

using System;
public class Program
{
public static void Main()
{
Console.WriteLine(A.GetInstance());
Console.WriteLine(A<int>.GetInstance());
Console.WriteLine(A.GetInstance<bool>());
/*
output :
Program+A
Program+A`1[System.Int32]
Program+A`1[System.Boolean]
*/
}
// classes
public class A : A<object>
{
// non-generic method in non-generic class
public static A GetInstance()
{
return new A();
}
// generic method
public static A<T> GetInstance<T>()
{
return new A<T>();
}
}
public class A<T>
{
// non-generic method in generic class
public static A<T> GetInstance()
{
return new A<T>();
}
}
}

public class A<T>
{
public static A<T> GetInstance()
{
return new A<T>();
}
}
public class A : A<object>
{
public static new A GetInstance()
{
return new A();
}
public static A<T> GetInstance<T>()
{
return new A<T>();
}
}
Notice the new keyword to the left of the A GetInstance().

Looks like this is what you want:
public class A : A<object>
{
public static A<T> GetInstance<T>() => new A<T>();
public new static A GetInstance() => new A();
}
public class A<T>
{
public static A<T> GetInstance() => new A<T>();
}
Then use it like this:
var a = A<int>.GetInstance();
var b = A.GetInstance<int>();
var c = A.GetInstance();
However, normally you'd expect to see generic types inherit from their non-generic equivalent, not the other way round (e.g. IEnumerable<T> : IEnumerable)

How about just making a factory like :
public class Factory<T>
{
public static A<T> Instance { get {return new A<T>(); } }
}

void Main()
{
var a = A.GetInstance();
var b = A<object>.GetInstance();
Console.WriteLine(a);
Console.WriteLine(b);
}
class A<T>
{
public static A<T> GetInstance()
{
return new A<T>();
}
}
class A : A<object>
{
}

Related

How to call methods of data member through a generic method

Considering the classes below, I would like to be able to write:
B b = new B();
b.f(1); // calls b._a.f(int)
b.f("howdy!"); // calls b._a.f(string)
Class A cannot be modified.
public class A
{
public void f(int i) { }
public void f(string s) { }
}
public class B
{
public void f<T>(T v)
{
_a.f(v); // fails
}
A _a = new A();
}
If you really want to simplify your f pass-through down to a single method, you'll have to use run-time type checking. I don't see any other way around it. Generics aren't going to work here.
public void f(object v)
{
if (v is int i)
_a.f(i);
else if (v is string s)
_a.f(s);
else
throw new InvalidOperationException();
}
I gather that you are hesitant to just expose _a because there are some methods on it that you would rather not be accessible to the caller? Could you introduce an interface, or would that be considered a modification to class A?
public interface IFoo
{
void f(int i);
void f(string s);
}
public class A : IFoo
{
...
}
public class B
{
public IFoo A => _a;
}

Adding a generic type constraint halfway through a method

I have two generic methods -
public CustomObject<T> MethodA<T>(T arg1) where T : class
{
...
return MethodB<T>(arg1);
}
public CustomObject<R> MethodB<R>(R arg2) where R : class, IInterface
{
...
return new CustomObject<R>();
}
The problem is clearly that I can't call MethodB with a type that doesn't implement IInterface (which T doesn't). But what if I did this -
public CustomObject<T> MethodA(T arg1) where T : class
{
...
var casted = arg1 as IInterface;
if (casted != null)
{
return MethodB<T>(casted);
}
}
Obviously this doesn't compile, yet it should, no? How can I let the compiler know that I know that casted implements IInterface and is a class so the call to MethodB is fine? The big wrinkle in here is probably that I'm trying to return CustomObject<T>.
You need to use reflection to make this work.
Try this:
public CustomObject<T> MethodA<T>(T arg1) where T : class
{
if (arg1 is IInterface)
{
var method = this.GetType().GetMethod("MethodB").MakeGenericMethod(arg1.GetType());
return (CustomObject<T>)method.Invoke(this, new [] { arg1 });
}
return null;
}
Because your CustomObject<T> is generic, it's problematic. For example, CustomObject<object> is not interchangeable with CustomObject<string>, but you can convert between the two.
You could do this as a workaround:
public class CustomObject<T> where T : class {}
public interface IInterface { }
public static class CustomObjectConverter
{
public static CustomObject<T1> ConvertTo<T1, T2>(CustomObject<T2> other)
where T1 : class
where T2 : class
{
return new CustomObject<T1>();
}
}
public CustomObject<T> MethodA<T>(T arg1) where T : class
{
if (arg1 is IInterface inf)
{
var b = MethodB(inf);
return CustomObjectConverter.ConvertTo<T,IInterface>(b);
}
return null;
}
public CustomObject<T> MethodB<T>(T arg2) where T : class, IInterface
{
return new CustomObject<T>();
}

Instantiating proper generic class by type parameter in C#

I have this code to perform operations under objects of Base class:
class Program
{
static void Main(string[] args)
{
var list = new List<Base>() { new A(), new B() };
var v = new Visitor();
list.ForEach(e => e.Accept(v));
}
}
public abstract class Base
{
public abstract void Accept(Visitor visitor);
}
public class A : Base
{
public override void Accept(Visitor visitor) => visitor.Visit(this);
}
public class B : Base
{
public override void Accept(Visitor visitor) => visitor.Visit(this);
}
public class Visitor
{
Writer writer = new Writer();
public void Visit(A a) => writer.Write(a);
public void Visit(B b) => writer.Write(b);
}
public class Writer
{
public void Write(A a) => Console.WriteLine("A");
public void Write(B b) => Console.WriteLine("B");
}
I want to divide Writer into separate classes, because there will be many other entities with complex hierarchy. It could be:
public interface Writer<T> where T : Base
{
void Write(T t);
}
public class WriterA : Writer<A>
{
public void Write(A t) => Console.WriteLine("A");
}
public class WriterB : Writer<B>
{
public void Write(B t) => Console.WriteLine("B");
}
but I don't know how to instantiate proper classes by the given type parameter rather than calling them explicitly. Thanks.
You will need to write WriterFactory:
class WriterFactory{
Dictionary<string, Func<object>> _creators = {
{ "A", ()=> new WriterA() },
{ "B", ()=> new WriterB() }
};
public Writer<T> Create<T>(){
return (Writer<T>)_creators[typeof(T).Name]();
}
Than you can use it in Visitor:
public class Visitor
{
Writer writerFactory = new WriterFactory();
public void Visit(A a) => writerFactory.Create<A>().Write(a);
public void Visit(B b) => writerFactory.Create<B>().Write(b);
}

How can I return a class instance with a generic type as an interface with a generic type?

When I have a simple Class and Interface, I can do this:
public class Foo : IFoo
{
public IFoo Instance()
{
return this;
}
}
Is there a way to do the same thing when both are generics?
public class Base<T, TI>
{
public TI Instance()
{
return this; // Nope
return (T) this; // Nope
}
}
public class Foo : Base<Foo, IFoo>
{
}
However I try to do this, I'm getting a "cannot implicitly convert type" error.
C# does not support this.
The best you can do is
public class Base<T, TI> where T : Base<T, TI>, TI
{
public TI Instance()
{
return (TI) (object) this; // Yep
}
}

Returning the type of an inherited class

Consider:
class BasicType
{
public BasicType() { }
public T Save<T>() where T : BasicType
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType
{
public DerivedType(BasicType b) { }
}
public static void Main()
{
DerivedType d = new DerivedType();
d = d.Save<DerivedType>();
}
This works, but being forced to specify the type each time I call Save is a drag.
Is there some way to change the BasicType.Save method such that it will always return an instance of the actual type (derived or base) of the instance on which Save is being called?
Generics are not needed in this case.
I think this should be enough:
public BasicType Save()
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (BasicType)Activator.CreateInstance(this.GetType(), b);
}
Anyway you should be carefull with this as the inherited classes may not have the expected constructor.
Is better to override the save method, or at least the specific part.
You could change your definition of BasicType so that you're forced to provide the type of T at the point of inheritance.
Something like this:
class BasicType<T> where T : BasicType<T>, new()
{
public BasicType() { }
public T Save()
{
T b = new T();
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType<DerivedType>
{
public DerivedType() { }
}
class Program
{
static void Main(string[] args)
{
DerivedType d = new DerivedType();
d = d.Save();
}
}
Something like this.
class BasicType
{
public BasicType()
{
}
protected virtual T Save<T>()
{
BasicType b = DataContext.Save(this); //Returns a BasicType
return (T)Activator.CreateInstance(typeof(T), b);
}
}
class DerivedType : BasicType
{
public DerivedType(BasicType b)
{
}
public DerivedType Save()
{
return base.Save<DerivedType>();
}
}
public static void Main()
{
DerivedType d = new DerivedType(new BasicType());
d = d.Save();
}

Categories