friends!
So I have been writing a simple program. Basically, I have a class (3 strings, 1 int, some methods). I am initializing the values of objects of this class from a text file. I am using List for this.
The problem is that initialization is a separate function. I had List BOTH declared AND initialized in this function. However, I might need it in other functions, including "Program.Main".
Should I make a "Global" class and put make a public List< Class > ? I decided to just declare it in my Program.Main function as of now. However, I am not sure, if a List is passed by value or by reference. I found a page on the Web, which suggests using ref keyword. Now I have:
public Class FooClass
{...}
class Program
{
static void Main(string[] args)
{
List<FooClass> fooDB = new List<FooClass>;
initFromFile(ref fooDB);
}
private static initFromFile(ref List<FooClass> fooDB)
{
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}//initFromFile
}//Program
Should I keep on working like this? Or are there any crucial suggestions? Maybe "ref" isn't a good practice at all?
TLDR: Should i make a global List or pass it as a reference or another way(suggest). If passing by reference, then should I use a ref keyword or is there another way?
Thanks in advance,
~~~hlfrmn
The way your program is structured is just fine, except there's no need toi use ref. List<T> is a reference type, meaning that the value that is passed to the function is actually a reference ("pointer" in C/C++ terms) to a List<T> instance. So any modifications to the list within the method will be available when the function returns.
The only reason you would use ref is if you wanted to point fooDB to a new instance:
private static initFromFile(ref List<FooClass> fooDB)
{
fooDB = new List<FooClass>; // if the parameter was not passed by reference
// this instance would not be used by the caller.
using (StreamReader ... ){
while( ... )
{
...
fooDB.Add(new FooClass(args))
}}
}//initFromFile
EDIT
Reading the first part of your question more closely, it seems like fooDB should possibly be a class member that is initialized:
class Program
{
private static List<FooClass> fooDB;
static void Main(string[] args)
{
initFromFile();
foreach(FooClass f in fooDB)
{
// do something
}
}
private static initFromFile()
{
fooDB = new List<FooClass>();
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}//initFromFile
}//Program
Generic lists are reference types hence you don't need to use ref keyword.If you make a change in your list on your method, it will affect your actual list.
Unless you're trying to set the value of fooDB directly inside the initFromFile function, you don't need to pass it as a ref parameter. Note that classes in .NET are reference types, so when you pass the list to method, the method parameter refers to the same instance that was passed in (as opposed to value types). ref parameters are used to modify what value that the both the parameter and the variable that was passed into the method reference. Using ref parameters is almost never necessary in typical .NET development.
Just pass it normally, and it will work:
static void Main(string[] args)
{
List<FooClass> fooDB = new List<FooClass>;
initFromFile(fooDB);
}
private static initFromFile(List<FooClass> fooDB)
{
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}
Given the code sample above, I would suggest that your initFromFile() method just return the list, i.e.
public Class FooClass
{...}
class Program
{static void Main(string[] args)
{
var fooData = initFromFile();
}
private static List<FooClass> initFromFile()
{
var fooDB = new List<FooClass>();
using (StreamReader ... ){
while( ... )
{
...
fooDB.Add(new FooClass(args))
}}
return fooDB;
}//initFromFile
}//Program
Related
I want to be able to assign functions from classes to variables
Ex:
namespace test
{
class init
{
static void Main(string[] args)
{
var toSingle = BitConverter.ToSingle;
}
}
}
ERROR The delegate type could not be inferred.
I rather think you might want using static (applied to the top of the file with your other using imports, or just inside your namespace):
using static BitConverter;
This will allow you to simply call ToSingle(...) anywhere in your class.
using static docs
Alternatively, if you really want to assign it to a variable, you could potentially assign it to a delegate (here I'll use Func):
Func<byte[], int, float> toSingle = BitConverter.ToSingle;
Though this won't work if you want to use the overload that takes a ReadOnlySpan<Bye> because it can't be a generic parameter.
Probably a very simple question, and maybe I'm not even doing it right in the first place. Done some research and having trouble understanding the second part.
Let's say I have two methods in C#, and I want to send the value of that variable to another method. This is how I've accomplished it, sending variable1s value to method 2
public void methodOne(string variable1)
{
variable1 = "testing";
myClass p = new myClass();
p.methodTwo(variable1);
}
public void methodTwo(string variable1)
{
Console.Write(variable1);
}
So this sends the information in variable1 from methodOne to methodTwo.
But what if I wanted to modify the variable in methodTwo, and then send it back to methodOne? Would I just do the same exact thing in methodTwo and utilize this again?
myClass p = new myClass();
p.methodOne(variable1);
My issue is obviously if I utilize that code, I'd get stuck in an infinite loop of going back and forth unless I added a break condition. It makes me think maybe I'm not even correctly considering how to do this, and there's an easier way I'm missing.
What you want to do is pass the variable ByRef, using the ref keyword.
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Method1();
}
private static void Method1()
{
int myVar = 5;
Console.WriteLine($"myVar in Method1: {myVar}"); // 5
Method2(ref myVar);
Console.WriteLine($"myVar in Method2: {myVar}"); // 10
}
private static void Method2(ref int AnotherVar)
{
AnotherVar = 10;
}
}
}
If I only register one method of one class to a delegate, I can use the delegate.Target, but when I subscripe more methods from different classes this does not work anymore. Is there another way to access the subscribers list of this delegate?
Here is the code: The foreach loop is being evaluated to null at runtime (it compiles)
public delegate void WriteMessage(string msg);
internal class Program
{
private static void Main(string[] args)
{
var myClass = new MyClass();
var writer = new WriteMessage(myClass.WriteMessage);
writer += SaySomething; //method in this class
writer += myClass.SayShit; //instance class
writer += AnotherClass.Say; //static class
foreach(string target in (string[])writer.Target)
{
Console.WriteLine(target);
}
Console.ReadLine();
}
private static void SaySomething(string msg)
{
Console.WriteLine("HI!!!!");
}
}
complete code:
http://pastebin.com/AzzRGMY9
Delegate[] list = delegate.GetInvocationList();
That will get you an array of Delegate objects, which you can use to get the list of Targets.
This is just additional information from the accepted answer, as I am looking the same information online.
If you want to invoke all registered methods upon receiving all the invocation list, you can use this code:
Delegate[] listAllRegisteredMethods = writer.GetInvocationList(); //writer is the variable based on the question example
foreach(Delegate c in listAllRegisteredMethods )
{
object[] p = { }; //Insert your parameters here inside the array if your delegate has parameters
c.DynamicInvoke(p); //Invoke it, if you have return values, assign it on a different variable
}
Can I locally reference a class in C#, instead of an instance of a class? The following code won't compile but, as an example, something like:
void someFunc()
{
var a = System.Math;
var b = a.Abs(4);
}
edit: In the real program it's not the System.Math class and I'm wanting to construct the class and return the constructed value. I didn't think originally that the context in which I wanted to use the class would be relevent, and probably it shouldn't be.
Anastasiosyal has an interesting idea with using a local Delegate to do it.
You can reference a class:
Type math = typeof(System.Math);
But you cannot call static methods on it using regular dot syntax:
// Wont compile:
math.Abs(5);
If you just want to shorten (and IMHO obfuscate) your code, you can reference classes with aliases via a using directive:
// Untested, but should work
namespace MyUnreadableCode {
using m = System.Math;
class Foo {
public static Int32 Absolut(Int32 a) {
return m.Abs(a);
}
}
}
You cannot assign a variable a value of a static class. The question is why would you want to do this, there are probably other ways that you could tackle your problem
e.g. you could use delegates to assign the operation you want to perform:
Func<int,int> operation = Math.Abs;
// then you could use it like so:
int processedValue = operation(-1);
In c# they're called Types. And you can assign them like:
Type a = typeof(SomeClass);
However, you would have to instantiate it to use it. What I believe you want is a static import like in java, but unfortunately, they do not exist in c#.
Short answer: Not like what you have above.
In C# 6.0 they introduced a static import feature, which can solve the problem.
using static System.Math;
class MyProgram
{
static void Main(string[] args)
{
var b = Abs(4); // No need to specify the name of Math class
}
}
As I understand you need to refer to the class with short name? try this (on top of the file, inside using statements section):
using m = System.Math;
later in your code:
m.Abs(...)
Makes sense?
No. It's not possible to treat a Type as a value where instance methods bind to static methods on the original type. In order to do this you would need to construct a new type which forwards it's method calls to the original type.
class MyMath {
public int Abs(int i) {
return Math.Abs(i);
}
}
var x = new MyMath();
In c# it's possible to create a list of functions like so:
var myList = new List< Func<Foo> >();
This will allow functions (delegates) that take no arguments and return a value of type Foo to be added to the list. So something like:
Foo myFunc1() { ... }
would be a valid member of that list. My question is, how do I declare the type for a templatized function? How can I construct a List<> that will hold functions of the form:
T myFunc2<T>() { ... }
You need to do that inside a templatized class or method. Then you can refer to the generic type T just as you would refer to the specific type Foo.
In other words:
public class FuncContainer<T>
{
private List<Func<T>> list = new List<Func<T>>();
public void Fill()
{
// Initialize list
}
}
I think the other answers so far have misunderstood the problem... and I don't think you can actually do it, if I've read it correctly. Am I right in saying you'd like to be able to write this:
List<???> list = new List<???>(); // This line won't work
list.Add(Method1);
list.Add(Method2);
...
static int Method1() { ... }
static string Method2() { ... }
If I've misunderstood, and a simple generic type parameter of T in your method or class suffices, I'll delete this answer :)
The closest you could come to the above would be something like this:
public class FuncList
{
private readonly List<Delegate> list = new List<Delegate>();
public void Add<T>(Func<T> func)
{
list.Add(func);
}
}
You'd then use it as:
FuncList list = new FuncList();
list.Add<int>(Method1);
list.Add<string>(Method2);
Quite what you'd do with the list afterwards is tricky... what did you have in mind?
Yes this first signature is completely valid.
The signature of the last function you suggested is the following
List<Func<T>> x;
This holds a list of delegates which take no arguments and produce a T value.