Let say I have a Student class
class Program
{
delegate bool del2(Student s); //I have to put this delegate before Main?
static void Main(string[] args)
{
List<Student> listStudent = new List<Student>()
{
... //adding student instances...
};
//delegate bool del2(Student s); Q1: why compile error if I put it here?
Predicate<Student> del1 = check;
Student s = listStudent.Find(del1);
Console.WriteLine("s is" + s.Name);
}
public static bool check(Student s) //Q2:why it need to be static method?
{
return s.Name == "Michael";
}
}
I have two questions:
Why I have to put del2 before the main method? del1 is a Predicate delegate, I can put it inside the main method, del2 is also a delegate, why I can't put it inside the main method too?
Why the check method has to be static?
Short answer:
You should declare delegate and Predicate as it is done in the MSDN documents, because off course you should.
Long Answer:
You don't have to put that delegate before Main. You just can't put it inside Main. This is a type declaration. And that type(Delegate with certain signature you declared) is meant to be used for passing functions as parameters. Things you declare in main, or any other method will be valid just in that method's scope. Even if you could declare a delegate in a method, the signature would not be defined( and recognizable) at anywhere else and this would be useless.
Actually the method you assigned to a Predicate doesn't have to be static, it just have to be there when you assign it. Static functions are available without creating an instance of their class. They are independent of objects of that class. Non-static methods belong to their objects and they are specific to their objects. Their specific object code is created with object creation. So you can use a non-static function, if an available object has it. Say Student class have a non-static check method. You can do this:
Student s2= new Student();
Predicate<Student> del1 = s2.check;
Related
Hi I just started C# and I ran into this problem. Below is my code. I'm trying to have ViewH be displayed but it sends me an error that it does not exist in the current context. I'm not sure what it's asking.
class MainClass
{
public static void Main(string[] args)
{
Ranger r1 = new Ranger();
ViewH(r1);
// ViewV();
}
}
This is where it is linked.
class View
{
public void ViewH()
{
Console.WriteLine("Name Health Endurance Bonus Tool");
Console.WriteLine("_______________________________________________________");
}
public void ViewV()
{
Console.WriteLine("Name: ");
Console.WriteLine("Health: ");
Console.WriteLine("Endurance: ");
Console.WriteLine("Bonus: ");
Console.WriteLine("Tool: ");
}
}
When you want to call a method from another class, you have two options:
The method is an instance method, i.e., it doesn't have a static modifier: you must instantiate the class (create an object with new) and then call the method on the object:
var view = new View();
view.ViewH(); // Note that ViewH is declared without a parameter,
// so we can't pass it an argument.
The method is static, i.e., it has a static modifier: call the method on the type name:
View.ViewH();
An instance method can access other instance members of the class like fields, properties or other methods. Each instance, i.e., each object created from it, has its own set of values stored in fields and properties. On the other hand, static fields and properties exist exactly once.
If all members of a class are static, you can mark the class itself as static. This makes it clear, that no instances can be created with new.
Only non-static classes can inherit from other classes an implement interfaces.
See also:
Inheritance (C# Programming Guide)
Static Classes and Static Class Members (C# Programming Guide)
Static and instance members in the article Classes (Language reference, C# 6.0 draft specification)
My understanding of Actions in C# is that they are just a specific version of a delegate, namely one with no parameters and no return type.
If I create a class like this...
class TrainSignal
{
public delegate void TrainsAComing();
public void HerComesATrain()
{
TrainsAComing();
}
}
...it won't compile since I haven't created an instance of the delegate. However if I replace the delegate definition with that of an Action like below it compiles:
class TrainSignal
{
public Action TrainsAComing;
public void HerComesATrain()
{
TrainsAComing();
}
}
I thought perhaps that maybe an Action is static or something like that (thereby allowing us to call it by it's name without instantiating it) but that doesn't seem to be the case.
Can anyone explain why the second code block is legal?
This line
public delegate void TrainsAComing();
defines a public delegate type called TrainsAComing, nested inside your class. This would let users create delegates of type TrainSignal.TrainsAComing, but TrainSignal would have no member to store an instance of such delegate.
In other words, declaration of the delegate does not define a member of delegate type. You need another declaration for that:
class TrainSignal
{
public delegate void TrainsAComing(); // The delegate type
public TrainsAComing OnTrainsAComing; // The member of delegate type
public void HerComesATrain()
{
OnTrainsAComing();
}
}
Action, on the other hand, is already a type, similar to delegate TrainsAComing from your example. Hence, the definition
public Action TrainsAComing;
makes TrainsAComing a member of TrainSignal capable of storing a delegate.
An Action field is a field like any other. It's a ref type, so the field is null initialized. You will receive a NullReferenceException. This is perfectly safe but not useful.
Maybe you meant to actually reference a function?
Action TrainsAComing = () => Console.WriteLine("...");
Or maybe, the confusion comes from the fact that the first code snippet declares a delegate type and the second one declares a field of a delegate type.
I have an asbtract class and I have classes that are devired from it. I have an attribute called PluginEventAttribute that works like so:
[PluginEventAttribute(PluginEvent.Load)]
public void OnLoad()
{
Log("Test Plugin loaded!");
}
I want my code to check if there is a method that uses that attribute, and if so, call it with custom parameters. How can I do that in C# winforms?
You just have to enumerate the instance methods and call the method if it has said attribute. Here's a working example (I hope I got your intent correctly) :
using System;
using System.Reflection;
class Program
{
class MyAttr : Attribute { }
abstract class Base { };
class Derived : Base
{
[MyAttr]
public void foo() { Console.WriteLine("foo"); }
public void bar() { Console.WriteLine("bar"); }
}
static void Main()
{
Base someInstance = new Derived();
foreach (var m in someInstance.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (m.GetCustomAttribute(typeof(MyAttr)) != null)
{
m.Invoke(someInstance, null); // prints "foo"
}
}
Console.ReadLine();
}
}
You may change the null argument in the call to Invoke to the array of arguments you wish to pass to the function. The contents of that array must match the function signature.
This has nothing to do with WinForms. It's all about CLR runtime and its type system.
I don't know any way how you could "just do it".
You can check if a method M has an attribute A only if you have a MethodInfo object that describes that method (methodinfo.GetCustomAttributes())
You can get MethodInfos in several ways, but the easiest and most obvious is to get the Type object and ask it about its methods (type.GetMethod()/type.GetMethods()).
You can get a Type object in several ways too. If you have any object at hand, you can call its GetType() method. Or, you can ask an Assembly object (that describes a DLL or EXE) about the Types it defines. (..)
So, if you have a foo object that someone already created:
call foo.GetType()
loop over type.GetMethods()
call method.GetCustomAttributes(typeof(YourAttribute))
check if it was found
Now if you notice that it as been found, you will end up having a MethodInfo that matches a method with that attribute. The only thing left is to call that method with methodinfo.Invoke and to pass it both parameters and the foo object.
Situation gets tricky if you don't have a foo object that you want to scan for methods. You must get the whole assembly, scan all types, scan all their methods. You end up with matching MethodInfo again. But you don't have any object to call the method found upon. Either that method will need to be static (so callable without target object) or you will need to somehow get matching object, too.
When I'm trying some code to learn about passing a reference of an object to a method, I get an error when I try to remove the static in the methods head. The error message says: An object reference is required for non-static field, method or property...... But isn't there a reference in the parameter already? I have seen code that don't use static, so why does this not work? I know that static is used when method is used from classes that isn't objects. Some explanation is appreciated to understand. Thanks!
// Method
internal static string ChangeName(Box obj)
{
return obj.BoxName;
}
EDIT: I added the whole code. Is the problem that I'm calling from inside the main method that is static?
class Program
{
static void Main(string[] args)
{
Box box1, box2;
box1 = new Box("Nick","R90",1);
box2 = new Box("Hanna","B27",2);
Console.WriteLine(ChangeName(box2));
Console.Read();
}
// Methods
private static string ChangeName(Box obj)
{
return obj.BoxName;
}
}
A static method is called like this:
MyClass.Method(arg);
An instance method is called like this:
MyClass myInstance = new MyClass();
myInstance.Method(arg);
The two are not compatible.
If you want to change the method signature, you also need to change every place where the method is called.
EDIT: You are using the unqualified call. Here are the rules for using an unqualified call.
A static method can call a static method.
A static method cannot call an instance method. (This is your problem.)
An instance method can call a static method.
An instance method can call an instance method.
This method should really be implemented as an instance method in the Box class. You would then say:
Console.WriteLine(box2.ChangeName());
If you don't have access to the Box code, and then you could either write an extension method, or keep the method static as per your example.
Probably the error is where you are calling this method; if you are calling from a static method, you must call against an object instance explicitly or call a static method.
I just stumbled over a very interesting problem. Giving the following code:
using System;
class Program
{
class A { }
class B : A { }
private static void MyMethod(A a) /* first method */
{
Console.WriteLine("A"); ;
}
private static void MyMethod(B b) /* second method */
{
Console.WriteLine("B");
}
static void Main(string[] args)
{
var a = new A();
// Call first method
MyMethod(a);
A b = new B();
// Should call the second method
MyMethod(b);
Console.ReadLine();
}
}
I would expect that the second method will be called because the runtime type of the variable is B. Any ideas why the code calls the first method instead?
Thanks,
Tibi
Some clarifications: Polymorphism means several forms which has nothing to do where you declare the method.
Method overloading is a form of polymorphism, ad-hoc polymorphism.
The way polymorphism is normally implemented by using late binding.
dynamic is the workaround for this problem.
The fact is that this is not working in C#(or Java) it is a design decission which I would like to understand why was made, and none of the answers is answering this question.
/Tibi
This isn't an example of polymorphism at all. Polymorphism comes in to play when you call methods ON the object, not when the object is used as a parameter. This is just a simple example of method overloading.
You declared b as being of type A, so the compiler is going to link to the overload that uses type A. The linker doesn't care that B is a subclass of A, it just picks the overload with the closest signature to the declared types (not the actual types) of the parameters passed in.
if you want to force it to use the 2nd method, cast b in to type B in the method call.
MyMethod((B)b);
Method overloading in C#, by default, is determined statically at compile time. Since you are passing a statically typed variable of type A, it will statically bind to method with the A overload. Use the dynamic keyword to get the behavior you want.
static void Main(string[] args)
{
dynamic d = new A();
// Call first method
MyMethod(d);
d = new B();
// Call the second method
MyMethod(d);
Console.ReadLine();
}
It's not calling the second method because the reference to b itself is of type A. While b contains a reference to an instance of B, that is not an actual type of B, so the overload that uses an A reference is chosen.