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);
}
Related
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.
//Program.cs
public interface TestVal
{
//Input Param
string Input { get; }
//will return output
TestValRes ValidateRe(string input);
}
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
//TestvalRes.cs
public interface TestvalRes
{
string Input { get; }
bool IsValid { get; }
}
So I just want to pass a string to the TestVal, do validation and call TestvalRes to return whether it is Valid or not, and if Invalid, why? So the validation will be done in the first public interface - TestVal, however I still need to call it inside the Main(), right?
First off, I'd recommend following C# naming conventions and name your interfaces ITestVal and ITestValRes respectively.
Next, static method cannot call instance methods in the same class (without creating an instance and using that). You need to create an instance of the class and pass control of the application flow to that:
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
I am working on a class that will have a multiple instances and different delegate function will be passed via the constructor for each object.
how can i pass a function as delegate to MissionGenerator class and force the compiler (at design time) to restrict only a function that belongs to a class that implements IDelegateMission interface. or maybe even better, if possible: belongs to class that implements IDelegateMission and from "type" RaiseTask ().
please take a look at the code below, it shows quite clear what I wish to achive.
// delegate type for tasks
public delegate void TaskDelegate();
public class MissionGenerator
{
protected TaskDelegate MissionToInvoke;
public MissionGenerator(TaskDelegate mission)
{
this.MissionName = MissionName;
}
}
interface IDelegateMission
{
System.DayOfWeek ExecutionDay { get; set; }
int HourOfExecution { get; set; }
void RaiseTask();
}
class Skarim: IDelegateMission
{
// class implement all IDelegateMission methods...
public void RaiseTask()
{
// this is the function to pass as TaskDelegate...
}
}
class MainClass
{
private void MainMethod()
{
MissionGenerator sekerMission = new MissionGenerator(new Skarim().RaiseTask);
}
}
Thank you.
Building on Evk's comment, do something like this:
public delegate void TaskDelegate();
public class MissionGenerator
{
protected TaskDelegate MissionToInvoke;
public MissionGenerator(IDelegateMission mission)
{
MissionToInvoke = mission.RaiseTask;
}
public void StartMission() => MissionToInvoke();
}
public interface IDelegateMission
{
void RaiseTask();
}
public class Skarim : IDelegateMission
{
public void RaiseTask() => Debug.WriteLine("Yo.");
}
public class MainClass
{
private void MainMethod()
{
var sekerMission = new MissionGenerator(new Skarim());
sekerMission.StartMission();
}
}
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();
I am creating a C# library with some reusable code and was trying to create a method inside a method. I have a method like this:
public static void Method1()
{
// Code
}
What I would like to do is this:
public static void Method1()
{
public static void Method2()
{
}
public static void Method3()
{
}
}
Then I could choose either Method1.Method2 or Method1.Method3. Obviously the compiler isn't happy about this, any help is much appreciated. Thanks.
If by nested method, you mean a method that is only callable within that method (like in Delphi) you could use delegates.
public static void Method1()
{
var method2 = new Action(() => { /* action body */ } );
var method3 = new Action(() => { /* action body */ } );
//call them like normal methods
method2();
method3();
//if you want an argument
var actionWithArgument = new Action<int>(i => { Console.WriteLine(i); });
actionWithArgument(5);
//if you want to return something
var function = new Func<int, int>(i => { return i++; });
int test = function(6);
}
Yes, when C# 7.0 is released, Local Functions will allow you to do that. You will be able to have a method, inside a method as:
public int GetName(int userId)
{
int GetFamilyName(int id)
{
return User.FamilyName;
}
string firstName = User.FirstName;
var fullName = firstName + GetFamilyName(userId);
return fullName;
}
Note that public (and similar modifiers) are not supported C# programming guide:
Because all local functions are private, including an access modifier, such as the private keyword, generates compiler error CS0106, "
This answer was written before C# 7 came out. With C# 7 you can write local methods.
No, you can't do that. You could create a nested class:
public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}
public static void Method3()
{
}
}
}
You'd then call:
ContainingClass.NestedClass.Method2();
or
ContainingClass.NestedClass.Method3();
I wouldn't recommend this though. Usually it's a bad idea to have public nested types.
Can you tell us more about what you're trying to achieve? There may well be a better approach.
You can define delegates within your method with complete code and call them if you want.
public class MyMethods
{
public void Method1()
{
// defining your methods
Action method1 = new Action( () =>
{
Console.WriteLine("I am method 1");
Thread.Sleep(100);
var b = 3.14;
Console.WriteLine(b);
}
);
Action<int> method2 = new Action<int>( a =>
{
Console.WriteLine("I am method 2");
Console.WriteLine(a);
}
);
Func<int, bool> method3 = new Func<int, bool>( a =>
{
Console.WriteLine("I am a function");
return a > 10;
}
);
// calling your methods
method1.Invoke();
method2.Invoke(10);
method3.Invoke(5);
}
}
There is always an alternative of using a nested class within a class that will not be visible from outside and calling its methods, like:
public class SuperClass
{
internal static class HelperClass
{
internal static void Method2() {}
}
public void Method1 ()
{
HelperClass.Method2();
}
}
As of C# 7.0 you can do that:
public static void SlimShady()
{
void Hi([CallerMemberName] string name = null)
{
Console.WriteLine($"Hi! My name is {name}");
}
Hi();
}
This is called local functions, that is just what you were looking for.
I took the example from here, but further informatin can be found here and here.
Why you don't use classes?
public static class Helper
{
public static string MethodA()
{
return "A";
}
public static string MethodA()
{
return "A";
}
}
Now you can acces MethodA via
Helper.MethodA();
Older thread, but C# does have the concept of nested functions
Func<int> getCalcFunction(int total, bool useAddition)
{
int overallValue = 0;
if (useAddition)
{
Func<int> incrementer = new Func<int>(() =>
{
overallValue += total;
return overallValue;
});
return incrementer;
}
else
{
Func<int> decrementer = new Func<int>(() =>
{
overallValue -= total;
return overallValue;
});
return decrementer;
}
}
private void CalcTotals()
{
Func<int> decrem = getCalcFunction(30, false);
int a = decrem(); //result = -30
a = decrem(); //result = -60
Func<int> increm = getCalcFunction(30, true);
int b = increm(); //result = 30
b = increm(); //result = 60
}
Your nearly there
public static void Method1()
should be
public static class Method1{}
Don't you want to use nested class instead?
That's said, you seem to not respect the Single Responsibility Principle because you want a single method do more than one thing at a time.
Why don't you just Run a method within another
public void M1()
{
DO STUFF
}
public void M1()
{
DO STUFF
M1();
}