C# specialize generic class - c#

Is it possible to do the following specialization in C#? I can do this in C++ but do not understand how to achieve the same result in C#.
class GenericPrinter<T>
{
public void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinter<int>
{
public void Print()
{
Console.WriteLine("Specialized with int");
}
}
Added:
The problem with suggested GenericPrinterInt solution is that I need to explicitly create it. new GenericPrinter<int> will still print Unspecialized method.
What I want is to use this GenericPrinter from another generic class without the knoledge is T equal to int or something else.

I guess the closer you could get in C# would be:
class GenericPrinter<T>
{
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class IntPrinter : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
Otherwise, the answer is, you can't specialize in C#.
As Lyubomyr Shaydariv said in his comment:
C++ templates are not .NET generics. You can't.
From your edit I guess you will have some type checking to make.
You can do this with a dictionary for example.
class GenericPrinter<T>
{
private Dictionary<Type, Action> _actions
= new Dictionary<Type, Action>()
{
{ typeof(int), PrintInt }
};
public virtual void Print()
{
foreach (var pair in _actions)
if (pair.First == typeof(T))
{
pair.Second();
return ;
}
Console.WriteLine("Unspecialized method");
}
public virtual void PrintInt()
{
Console.WriteLine("Specialized with int");
}
}
Like you can see, you will have to make a method for each type, you want to handle. And you may also encounter some issues when you will try to manipulate T as int. Since, T is really generic (it hasn't any constraint), it will more likely act as an object in your code (not at runtime) you will have to cast it like that (int)(object)yourTVariable in your methods where you are sure that T is an int.
But for this part, I guess some of my peers, will have a better answer than me to give to you.
If it's just about displaying which type you are using:
public virtual void Print()
{
Console.WriteLine($"Specialized with {typeof(T).Name}");
}
But you won't have the unspecialized message anymore (and if you think about it, you can't have a GenericPrinter instantiated without specifying its type. Then it makes no sense to have a method that displays "unspecialized", you will always have a specified type)
Anyway, the answer is still the same, you can't specialize a generic in C#.

It isn't possible in C#.
You can use inheritance instead:
class GenericPrinter<T>
{
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinterInt : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
According to the updated question, I can only suggest you the following approach. You could create a static factory method in which you can check the type of T and instantiate an appropriate specialized class if the type matches the criteria:
class GenericPrinter<T>
{
public static GenericPrinter<T> Create()
{
if (typeof(int).IsAssignableFrom(typeof(T)))
return (GenericPrinter<T>)(object)new GenericPrinterInt();
if (typeof(double).IsAssignableFrom(typeof(T)))
return (GenericPrinter<T>)(object)new GenericPrinterDouble();
// Other types to check ...
return new GenericPrinter<T>();
}
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinterInt : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
class GenericPrinterDouble : GenericPrinter<double>
{
public override void Print()
{
Console.WriteLine("Specialized with double");
}
}
Some other generic class:
class SomeGenericClass<T>
{
public readonly GenericPrinter<T> Printer = GenericPrinter<T>.Create();
}
Usage sample:
var intClass = new SomeGenericClass<int>();
intClass.Printer.Print();
// Output: Specialized with int
var doubleClass = new SomeGenericClass<double>();
doubleClass.Printer.Print();
// Output: Specialized with double
var stringClass = new SomeGenericClass<string>();
stringClass.Printer.Print();
// Output: Unspecialized method

You can do it but you need to move your code into lambda expressions
or some flavor of lambdas.
It's not pretty but is fast ( no lookups ) and has the specialization.
You can tailor this to your needs
Cummon Microsoft we shouldn't have to do this.
How many improvements to .Net and no specialization.
public class GenericPrinter<T>
{
public static GenericPrint()
{
T thing = default(T)
switch(thing)
{
case int ival:
_Print = ()=>
{
Console.WriteLine("Specialized Int print Code");
};
break;
default:
_Print = ()=>
{
Console.WriteLine("Some generic print code");
};
break;
}
}
// will be unique for every type of T
public static Action _Print=null;
public void Print()
{
_Print();
}
}
Use would be the same
var printer = new GenericPrinter<int>();
printer.Print();

Related

C# calling member function with delegate

because of this post I create a new question to make my probleme more clear. I have a class with a next class member, so there will be a daisy chain of class instances. A function in my class calls another member function or all instances in the chain.
c ++ has a resonable solution for this problem. In C# I tried it with a delegate. I made a short program to show what I mean.
class Program {
static void Main(string[] args)
{
DaisyChain TestClass = new DaisyChain(1);
TestClass.AddClass(new DaisyChain(2));
TestClass.AllprintID();
}
}
class DaisyChain {
private int ClassID;
private DaisyChain NextClass;
public DaisyChain(int ID) {ClassID = ID; }
public void AddClass(DaisyChain newClass) {
if (NextClass == null) {
NextClass = newClass;
} else {
NextClass.AddClass(newClass);
}
}
public void AllprintID() {
DoForEach(this.printID);
}
public delegate void doFunc();
public void DoForEach (doFunc aMemberFunc) {
aMemberFunc();
if (NextClass != null) {
NextClass.DoForEach(aMemberFunc);
}
}
public void printID() {
Console.WriteLine(ClassID);
}
};
This example do not work correct, because the class instance is not part of the function call.
I can add a class argumnet to my member function and chang the delegate,
public void printID(DaisyChain me) {
Console.WriteLine(me.ClassID);
}
but then the function will be static and no longer usable in the normal way.
I would be happy if ther another solution.
The delegate type should have an extra argument, since you want to call printID on different objects. You can either add one to doFunc, or just use the built in Action<T> delegate type.
public void DoForEach (Action<DaisyChain> aMemberFunc) {
aMemberFunc(this);
if (NextClass != null) {
NextClass.DoForEach(aMemberFunc);
}
}
When calling DoForEach, you can either pass a lambda expression:
public void AllprintID() {
DoForEach(x => x.printID());
}
Or if you really like the method group syntax for some reason, write a local function printID:
public void AllprintID() {
void PrintID(DaisyChain chain) {
chain.PrintID();
}
DoForEach(PrintID);
}
// method names should start with a capital letter :)
public void PrintID() {
Console.WriteLine(ClassID);
}
Other code can still call PrintID as usual - code outside AllprintID won't even notice the local function.
You are trying to reinvent the wheel. Check LinkedList and LinkedListNode in the documentation. Here is an example to get you on the way:
var daisyChain = new DaisyChain();
daisyChain.Add(1);
daisyChain.Add(2);
class DaisyChain: LinkedList<DaisyChainLink>
{
public void Add(int id) => AddLast(new LinkedListNode<DaisyChainLink>(new DaisyChainLink(id)));
public void Print()
{
var link = this.First;
link?.Value.Print();
while (null != link?.Next)
{
link = link.Next;
link?.Value.Print();
}
}
}
class DaisyChainLink
{
public DaisyChainLink(int id)
{
Id = id;
}
public int Id { get; }
public void Print() => Console.WriteLine(Id);
}

How to pass 2 different types into a function param in c#?

In c# if I have this
private void Run(Web site) {
site.BreakRoleInheritance(false, false);
}
private void Run(ListItem folder) {
folder.BreakRoleInheritance(false, false);
}
How can I instead make 1 function that can accept either Site or Folder?
If Site and Folder are classes that you've created, then you can create a common interface which those classes inherit from. For example:
public interface IBreakable
{
void break();
}
public class Folder : IBreakable
{
public void break() { /* implementation here*/ }
}
public class Site : IBreakable
{
public void break() { /* implementation here*/ }
}
Usage
private void Run(IBreakable breakable)
{
breakable.break();
}
Edit
Here's a solution based on reflection, although this is not ideal.
void Run(object obj)
{
MethodInfo method = obj.GetType().GetMethod("break");
if (!(method is null))
{
method.Invoke(obj, new object[] {});
}
}
Given
public class Foo
{
public void break() {Console.WriteLine("Foo");}
}
public class Bar
{
public void break() {Console.WriteLine("Bar");}
}
public class Bad
{
public void NotBreak() {Console.WriteLine("Bad");}
}
Usage
Foo foo = new Foo();
Bar bar = new Bar();
Bad bad = new Bad();
Run(foo);
Run(bar);
Run(bad);
Output
Foo
Bar
As a later answer from #Pedro pointed out, those specific classes derive from a common ancestor, and that would be the preferred option. Assuming you did not have that option:
You can use the C# dynamic type (sorry if that is not the latest doc, I couldn't find a newer one):
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic
Example:
using System;
public class Program
{
public static void Main()
{
var foo = new Foo();
var bar = new Bar();
DoSomething(foo);
DoSomething(bar);
}
private static void DoSomething<T>(T someObjectWithDoMethod)
{
((dynamic)someObjectWithDoMethod).Do();
}
}
public class Foo
{
public void Do() { Console.WriteLine("Foo is doing something"); }
}
public class Bar
{
public void Do() { Console.WriteLine("Bar is doing something"); }
}
.Net Fiddle: https://dotnetfiddle.net/MShLK5
Based on your comments to other answers, Web and ListItem are types defined in the Microsoft.SharePoint.Client.
Checking the SDK docs, both types derive from SecurableObject where the BreakRoleInheritance method is defined.
That being the case, all you need to do is define one method that takes a SecurableObject object as an input:
public void Run(SecurableObject item)
{
item.BreakRoleInheritance();
}
And you should be able to pass a Web and a ListItem to this same method.

Force override method if another method is overriden

Is there a way to force the override of a virtual method if another method is overriden?
public class BaseClass
{
protected virtual void A()
{
// a default action called first
}
protected virtual void B()
{
// a default action called second that,
// if A was overriden, makes no sense
}
}
EDIT
Thanks a lot for the Answers. It's very interresting to see how this could be achieved, but for my explicit case it's not critically important.
Also, i forgot to mention how those Methods would be used: (in BaseClass)
pulbic bool EditEntity(Guid id)
{
A();
// Some code that edits Entites
B();
}
No, you cannot. But this makes me think how could you achieve the same concept?
The best idea I came up with was declaring an interface which had the package of methods to override.
public interface IMyOverridablePackage
{
void A_Override();
void B_Override();
}
Then give the base class a protected method where the child class can explicitly override the set of methods.
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
So then here's two classes, one which does and one which does not override the set of methods:
public class NotOverriding : MyBaseClass
{
}
public sealed class Overriding : MyBaseClass, IMyOverridablePackage
{
public Overriding()
{
SetOverride(this);
}
void IMyOverridablePackage.A_Override()
{
Console.WriteLine("Overriding.A_Override");
}
void IMyOverridablePackage.B_Override()
{
Console.WriteLine("Overriding.B_Override");
}
}
And the implementation of the base class:
public abstract class MyBaseClass
{
private IMyOverridablePackage _overridablePackage;
public void A()
{
_overridablePackage.A_Override();
}
public void B()
{
_overridablePackage.B_Override();
}
private class MyDefaultPackage : IMyOverridablePackage
{
private readonly MyBaseClass _myBaseClass;
internal MyDefaultPackage(MyBaseClass myBaseClass)
{
_myBaseClass = myBaseClass;
}
void IMyOverridablePackage.A_Override()
{
_myBaseClass.A_Impl();
}
void IMyOverridablePackage.B_Override()
{
_myBaseClass.B_Impl();
}
}
protected MyBaseClass()
{
_overridablePackage = new MyDefaultPackage(this);
}
private void A_Impl()
{
Console.WriteLine("MyBaseClass.A_Impl");
}
private void B_Impl()
{
Console.WriteLine("MyBaseClass.B_Impl");
}
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
}
This does achieve the goal, but of course you have to ask 'how much to I want it?' Is it worth the extra code?
Here's a working dotnetfiddle: https://dotnetfiddle.net/xmPn20
Maybe you cannot force it via compiler errors, but you could write a test which asserts that the methods are in sync via some attributes. It would also be visible that there is some dependency.
A crude example would be something like this:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
public VersionAttribute(string version)
{
Version = version;
}
public string Version { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DependentAttribute : Attribute
{
public string DependentOnMethod { get; set; }
public string DependentOnVersion { get; set; }
}
[Dependent(DependentOnMethod = "OtherMethod", DependentOnVersion = "1")]
public static void FirstMethod()
{
}
[Version("1")]
public static void OtherMethod()
{
}
And the test that asserts the version numbers:
[Test]
public void TestVersions()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var customAttribute in method.GetCustomAttributes())
{
var dependent = customAttribute as DependentAttribute;
if (dependent != null)
{
var methodInfo = type.GetMethod(dependent.DependentOnMethod);
Assert.That(methodInfo, Is.Not.Null, "Dependent method not found");
VersionAttribute version = methodInfo.GetCustomAttributes().OfType<VersionAttribute>().FirstOrDefault();
Assert.That(version, Is.Not.Null, "No version attribute on dependent method");
Assert.That(dependent.DependentOnVersion, Is.EqualTo(version.Version));
}
}
}
}
}
thus, if you update one of your methods you would need to update the version number of either the Version attribute or the Dependent attribute. Hopefully better than nothing.
You may change your design :
public abstract class BaseClass
{
protected abstract void A();
}
public class BaseClassEx
{
protected sealed override void A()
{
// action Calling B
}
protected virtual void B()
{
// a default action called second
}
}
In the case of Equals (actually both Equals overloads, concrete type and object) and GetHashCode, Resharper includes a rule that shows a warning in its IntelliSense whenever you forget to implement one of these.
You could enforce it in your code with a runtime check in the constructor of the base class:
public class Base
{
public Base()
{
var baseA = typeof (Base).GetRuntimeMethod("MethodA", new Type[0]);
var baseB = typeof (Base).GetRuntimeMethod("MethodB", new Type[0]);
var derivedA = GetType().GetRuntimeMethod("MethodA", new Type[0]);
var derivedB = GetType().GetRuntimeMethod("MethodB", new Type[0]);
if (baseA.DeclaringType == derivedA.DeclaringType ^
baseB.DeclaringType == derivedB.DeclaringType)
throw new InvalidOperationException("You must override MethodA and MethodB together.");
}
public virtual string MethodA() { return "Hello"; }
public virtual int MethodB() { return 123; }
}

I don't understand what they mean when runtime will decide which overriden method gets called

polymorphism example:
public class animal
{
public void virtual speak()
{
Console.WriteLine("Animals can speak in many ways.");
}
}
public class dog : animal
{
public void override speak()
{
Console.WriteLine("I bark!");
}
}
static void main()
{
animal doggy = new dog();
doggy.speak();
}
output:
I bark!
I keep reading that the correct speak method is called during runtime, but is it not already hard coded and does the compiler not recognize which method it will invoke based on the virtual and override keywords?
Your compiler doesn't necessarily know which implementation will be the underlying type. Take, for example:
class A
{
public virtual void F() { Console.WriteLine("A"); }
}
class B : A
{
public override void F() { Console.WriteLine("B"); }
}
class Program
{
static A GetImpl(int i)
{
switch(i)
{
case 1:
return new A();
case 2:
return new B();
default:
// whatever
}
}
static void Main(string[] args)
{
var i = int.Parse(Console.ReadLine());
A a = GetImpl(i);
a.F();
}
}
How could the compiler possibly know if an A or a B is returned? It cannot, so the task of calling the correct method is delegated to the runtime.
If your code was something like
Animal anAnimal= NoahsArc.getNextAnimal();
anAnimal.speak();
Now you don't actually know what sort of animal you are going to get, so the runtime ensures the correct speak method is called.

Wrapping methods with different signatures, pre-and-post-invocation

How to avoid a pair of repetitive lines before and after invocations in sample below ?
Details: This is compileable mock of what is real larger code. Generally it is a layer of proxy classes containing service clients with variety of APIs. The repetitive part is pre- and post- invocation for every method of every client. Unfortunately there is no single signature for all possible methods, the pre- and post- parts need a pointer to client's channel and context.
Is it possible to apply something advanced like AOP, Generics, Delegates, Attributes etc. ? Thank you
using System;
namespace ConsoleApplication
{
class ClassServiceClient: IDisposable
{
public Object channel()
{
return "something";
}
public Object context()
{
return "something other";
}
}
class ClassA : ClassServiceClient
{
public Object methodA()
{
return "something other";
}
}
class ClassB : ClassServiceClient
{
public void methodB(string param)
{
return;
}
}
class ClassAProxy
{
public Object methodA()
{
using (ClassA client = new ClassA())
{
Program.preparation(client.channel()); //<---- repetitive part
Object result = client.methodA();
Program.postinvocation(client.context());//<---- repetitive part
return result;
}
}
}
class ClassBProxy
{
public void methodB(string param)
{
using (ClassB client = new ClassB())
{
Program.preparation(client.channel()); //<---- repetitive part
client.methodB(param);
Program.postinvocation(client.context());//<---- repetitive part
return;
}
}
}
class Program
{
public static void preparation(Object channel)
{
// Do something with channel
}
public static void postinvocation(Object context)
{
// Do something with context
}
static void Main(string[] args)
{
}
}
}
If you can use a common base class, you can easily use a public sealed method that does the invocation and a protected abstract method that does the logic, e.g.
class ProxyBase{
public void Method(params object[] args){
PreConditions();
Invoke(args);
PostConditions();
}
protected abstract void Invoke(object[] args);
}
class ClassAProxy{
protected override void Invoke(object[] args){
client.Method(args[0]);
}
}
You can achieve similar results functionally by declaring a InvocationHandler in your Program class that takes an action:
class Program{
public static void Invoke(object[] args, Action action){
PreConditions();
action();
PostConditions();
}
}
class ClassAProxy{
public void MethodA(int i){
Program.Invoke(() => client.Something(i));
}
}

Categories