Why can't I add this entry to my dictionary? - c#

I am attempting to make an application which gets and inputted URL via textbox, retrieves the HtmlCode of that website when a button is clicked and stores both in a dictionary which is then displayed in a listbox.
However, I haven't been able to implement any of it into the user interface yet due to having an issue when trying to add an entry to the dictionary. To retrieve the HtmlCode I am calling the method GetHtml however, i am getting an error when trying to add the website and the code to the dictionary.
Code Follows
namespace HtmlCheck
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
var dict = new SortedDictionary<string, WebsiteInfo>();
var list = (from entry in dict
orderby entry.Key
select entry.Key).ToList();
}
private static void addPerson(string websiteUrl)
{
dict.Add(websiteUrl, new WebsiteInfo { WebsiteUrl = websiteUrl, HtmlCode = getHtml(websiteUrl) });
}
private static SortedDictionary<string, WebsiteInfo> dict;
public string getHtml(string websiteUrl)
{
using (WebClient client = new WebClient())
return client.DownloadString(websiteUrl);
}
}
public class WebsiteInfo
{
public string WebsiteUrl;
public string HtmlCode;
public override string ToString()
{
string formated = string.Format("{0}\n---------------------------------- \n{1}", WebsiteUrl, HtmlCode);
return formated;
}
}
}
In the method
private static void addPerson(string websiteUrl)
{
dict.Add(websiteUrl, new WebsiteInfo { WebsiteUrl = websiteUrl, HtmlCode = getHtml(websiteUrl) });
}
the HtmlCode = getHtml(websiteUrl) is throwing an error:
"An object reference is required for the non-static field, method, or property 'HtmlCheck.Program.getHtml(string)'"
So my question is, why cant I add an entry to the dictionary with this information?
Thanks for your time.

You're getting that error because addPerson() is a static method (it is called without creating an instance of the Program class), but the getHtml() method is not static (so you need an instance of the Program class to call it).
Easy fix - make it static too:
public static string getHtml(string websiteUrl)
{
...
}
For the sake of completeness, you'd have to otherwise create an instance of the Program class before calling the getHtml() method:
private static void addPerson(string websiteUrl)
{
var p = new Program();
dict.Add(websiteUrl, new WebsiteInfo { WebsiteUrl = websiteUrl, HtmlCode = p.getHtml(websiteUrl) });
}

addPerson() is a static method, which means you can call it any time, without having an instance of the class to call it on. It then tries to call getHtml(), which is non-static, which means it can only be called through a valid instance of the class.
I suggest you do some research on static methods in C# to get your head around this.

Add "static" to your method;
public static string getHtml(string websiteUrl)

Related

Set returned value from method as public string in C#

I need to get string from one class to another class,
It is possible to set public string from method I mean like in this code:
class test
{
static void Main(string[] args)
{
load();
}
public class Data
{
public string datacollected { get; set; }
}
public static void load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
Data datacfg = new Data();
var datanew = System.Text.Json.JsonSerializer.Deserialize<List<Data>>(jsonString);
datacfg = datanew.First();
}
public string datacollected = datacfg.datacollected;
}
i want to use string datacollected in another class and in another public void
The datacollected member that is directly in the test class is not a property. It's a field. Fields that have an assignment on the same statement as the declaration are evaluated before* the class's constructor (ie: before the Main method runs).
You probably want it to be a property instead, which is evaluated each time you access the member. The simplest method to fix that is by adding a > after the equals.
public string datacollected => datacfg.datacollected;
You've got two other problems though.
datacollected (in the test class) isn't static. All of your methods are static, and therefor wouldn't be able to access the non-static member.
You've still got the problem where the datacfg is a local variable that is defined inside the load method. You can't use variables outside their defined scope.
Option 1: you only need the parsed file data in the method that called load.
Change load to return the parsed data, rather than save it to a class-global variable.
using System.Text.Json;
static class test
{
static void Main(string[] args)
{
Data loadedData = load();
}
public static Data load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
return JsonSerializer.Deserialize<List<Data>>(jsonString).First();
}
}
public class Data
{
public string datacollected { get; set; }
}
Option 2: If you really need some global variable, put the whole Data object up to a field instead. This doesn't use a property - there's really no advantage in this case.
using System.Text.Json;
static class test
{
// assuming you're using nullable reference types (the "?")
private static Data? loadedData;
static void Main(string[] args)
{
load();
Console.WriteLine(loadedData!.datacollected);
// "!" to tell compiler that you know loadedData
// shouldn't be null when executed
}
public static void load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
loadedData = JsonSerializer.Deserialize<List<Data>>(jsonString).First();
}
}
public class Data
{
public string datacollected { get; set; }
}
I'd go with Option 1 if at all possible.
* I don't remember if it's before, during, or after.
You can declare a class like this
public class UseData
{
private List<Data> _data=null;
public string datacollected
{
get
{
if (_data == null)
LoadData();
return _data.First().datacollected;
}
}
private void LoadData()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
_data = System.Text.Json.JsonSerializer.Deserialize<List<Data>>(jsonString);
}
}
which have a private list of data and it loads from your json file at first time you called. Next time you call it, as the private _data object is filled, it wont load again and the datacollected property returns the first data object's datacollected string property.

Error on static Class

public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.

The name 'functionname' does not exist in the current context

When trying to compile my c# windows app I am getting the following error:
The name 'GetActiveLB' does not exist in the current context
Here's the code that calls that function:
using F5LTMMaintenance;
......
private void btnLBSetA_Click(object sender, EventArgs e)
{
List<string> range = GetActiveLB();
foreach (string item in range)
{
// Do something with item
}
}
Then I have a class with the following:
namespace F5LTMMaintenance
{
public class F5LTM<T>
{
public List<T> GetActiveLB()
{
var client = new RestClient("mylb.domain.local");
var request = new RestRequest("mgmt/tm/cm/failover-status", Method.GET);
var queryResult = client.Execute<List<T>>(request).Data;
return queryResult == null ? new List<T>() : queryResult;
}
}
}
The GetActiveLB function does exist, its a public function so why am I getting this error? Any help would be appreciated.
It has to be used with an instance of F5LTM<T>.
e.g.:
var f5ltm = new F5LTM<string>();
List<string> range = f5ltm.GetActiveLB();
Alternatively, if you declare it as static like this:
public class F5LTM //not generic here
{
public static List<T> GetActiveLB<T>() //generic here and static
{
//unchanged
}
}
Usage:
List<string> range = F5LTM.GetActiveLB<string>();
Or with C# 6 using static syntax:
using static F5LTMMaintenance.F5LTM; //at top of file
List<string> range = GetActiveLB<string>();
This is as close as you can get to the code you posted.
Yes it's a public function but it's defined inside a different class than your calling event handler class. You need to create a instance of your class F5LTM<T> and on that instance call your method GetActiveLB() rather like
private void btnLBSetA_Click(object sender, EventArgs e)
{
F5LTM<Type> test = new F5LTM<Type>();
List<string> range = test.GetActiveLB();
You will need an instance of your F5LTM class (say typF5LTM), to be able to call typF5LTM.GetActiveLB(). Or you need to make GetActiveLB a static function to be able to call it without an instance like F5LTM.GetActiveLB();
As another poster pointed out, you have to call the method on the class.
F5LTM<string> listItems = new F5LTM<string>();
List<string> range = listItems.GetActiveLB();

Get Object reference not set to an instance of an object error from static member

I have a static class like this:
public static class ApplicationList
{
public static List<ApplicationsModel> ApplicationsModels { get; set; }
}
I want to use ApplicationsModels in another class
class Program
{
static void Main(string[] args)
{
GetApplicationNameFromAppConfigAndAddToApplicationList();
}
private static void GetApplicationNameFromAppConfigAndAddToApplicationList()
{
List<string> applicationName = ConfigurationManager.AppSettings["AppName"].Split(',').ToList();
foreach (var variable in applicationName)
{
ApplicationList.ApplicationsModels.Add(new ApplicationsModel { DateTime = DateTime.MinValue, Name = variable });
}
}
}
But i my ApplicationList is null and get this error
Object reference not set to an instance of an object.
This is static Prpoerty and we can't create instance form static Prpoerty
Well you have a
public static List<ApplicationsModel> ApplicationsModels { get; set; }
property which is not initialized.
Can do something like this, instead:
public static class ApplicationList
{
private static List<ApplicationsModel> appmodel = new List<ApplicationsModel>();
public static List<ApplicationsModel> ApplicationsModels
{
get { return appmodel ;}
}
//DON'T THINK YOU NEED A SET IN THIS CASE..
// BUT ADD IT, IF NEED
}
You get the null reference exception because the List<ApplicationsModel> ApplicationsModels is still null when you try to use it. Just declaring it as static doesn't means that the compiler or the framework adds for you the call to
ApplicationsModels = new List<ApplicationsModel>();
Short answer, add this line before loading your list:
ApplicationsModels = new List<ApplicationsModel>();
Longer answer:
You need to initialise your List before you can add to it.
This is because a (reference-type) property will be null by default, and it wouldn't make sense to do null.Add(item).
Solution 1: Initialise before loading:
The easy solution is to add an initialisation line before loading your list in your Get... method:
ApplicationsModels = new List<ApplicationsModel>();
However, this will reinitialise the list each time you call the Get method (which may or may not be what you want). You could place a check to only recreate the list if it is null, but if that's the behaviour you're after I'd lean towards one of the other solutions below.
Solution 2: Use an initialised field instead of a property:
Another way is to replace your property with an initialised field. Either:
public static List<ApplicationsModel> ApplicationsModels = new List<ApplicationsModel>();
Or:
public static List<ApplicationsModel> ApplicationsModels
{
get { return _applicationsModels; }
set { _applicationModels = value; } // Do you really want a set?
}
private static List<ApplicationsModel> _applicationsModels = new List<ApplicationsModel>();
Solution 3: Keep a property, but use a static constructor:
Another way is to use a static constructor in ApplicationList:
static ApplicationList()
{
ApplicationsModels = new List<ApplicationsModel>();
}

Is there a way to force static fields to be initialized in C#?

Consider the following code:
class Program
{
static Program() {
Program.program1.Value = 5;
}
static List<Program> values = new List<Program>();
int value;
int Value
{
get { return value; }
set {
this.value = value;
Program.values.Add(this);
}
}
static Program program1 = new Program { value = 1 };
static Program program2 = new Program { value = 2 };
static Program program3 = new Program { value = 3 };
static void Main(string[] args)
{
if (Program.values.Count == 0) Console.WriteLine("Empty");
foreach (var value in Program.values)
Console.WriteLine(value.Value);
Console.ReadKey();
}
}
It prints only the number 5, and if removed the code in the static constructor, it prints "Empty".
Is there a way to force static fields to be initialized even whether not used yet?
I need to have a static property named Values with returns all instances of the referred type.
I tried some variations of this code and some works for some types but doesn't for others.
EDIT: THE SAMPLE ABOVE IS BROKEN, TRY THIS ONE:
class Subclass<T> {
static Subclass()
{
Values = new List<Subclass<T>>();
}
public Subclass()
{
if (!Values.Any(i => i.Value.Equals(this.Value)))
{
Values.Add(this);
}
}
public T Value { get; set; }
public static List<Subclass<T>> Values { get; private set; }
}
class Superclass : Subclass<int>
{
public static Superclass SuperclassA1 = new Superclass { Value = 1 };
public static Superclass SuperclassA2 = new Superclass { Value = 2 };
public static Superclass SuperclassA3 = new Superclass { Value = 3 };
public static Superclass SuperclassA4 = new Superclass { Value = 4 };
}
class Program
{
static void Main(string[] args)
{
//Console.WriteLine(Superclass.SuperclassA1); //UNCOMMENT THIS LINE AND IT WORKS
foreach (var value in Superclass.Values)
{
Console.WriteLine(value.Value);
}
Console.ReadKey();
}
}
There is actually a way to force the initialization of the properties in this case. The change requires adding a type parameter to the base class to represent the future subclass of the base class that will contain the fields to be initialized. Then we can use the RuntimeHelpers.RunClassConstructor to ensure that the sub class static fields are initialized.
The following will yield the results that you are looking for:
class Subclass<TSubclass, T>
{
static Subclass()
{
Values = new List<Subclass<TSubclass, T>>();
// This line is where the magic happens
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(TSubclass).TypeHandle);
}
public Subclass()
{
if (!Values.Any(i => i.Value.Equals(this.Value)))
{
Values.Add(this);
}
}
public T Value { get; set; }
public static List<Subclass<TSubclass, T>> Values { get; private set; }
}
class Superclass : Subclass<Superclass, int>
{
public static Superclass SuperclassA1 = new Superclass { Value = 1 };
public static Superclass SuperclassA2 = new Superclass { Value = 2 };
public static Superclass SuperclassA3 = new Superclass { Value = 3 };
public static Superclass SuperclassA4 = new Superclass { Value = 4 };
}
public class Program
{
public static void Main()
{
foreach (var value in Superclass.Values)
{
Console.WriteLine(value.Value);
}
Console.ReadKey();
}
}
What is happening is, the call to RuntimeHelpers.RunClassConstructor(typeof(TSubclass).TypeHandle) forces the static constructor of TSubclass to execute if it has not already run. This ensures that the static fields have initialized first as per this line from https://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx :
If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.
Here is a dotnetfiddle demonstrating it working:
https://dotnetfiddle.net/MfXzFd
The answer to your question is 'well, yes'. But one of the two ways of "forcing" it is what you're already doing.
The relevant section in the language spec is Static constructors, and specifically:
The static constructor for a class executes at most once in a given
application domain. The execution of a static constructor is triggered
by the first of the following events to occur within an application
domain:
An instance of the class is created.
Any of the static members of the class are referenced.
If a class contains the Main method (Section 3.1) in which execution
begins, the static constructor for that class executes before the Main
method is called. If a class contains any static fields with
initializers, those initializers are executed in textual order
immediately prior to executing the static constructor.
But you're never setting the property -- instead you're setting the backing field directly, so not going through your logic to add to the static list when creating program1, program2 and program3.
i.e. you need to change:
static Program program1 = new Program { value = 1 };
static Program program2 = new Program { value = 2 };
static Program program3 = new Program { value = 3 };
to:
static Program program1 = new Program { Value = 1 };
static Program program2 = new Program { Value = 2 };
static Program program3 = new Program { Value = 3 };
Actually looks you misspelled 'value' -> 'Value'
So:
static Program program1 = new Program { Value = 1 };
static Program program2 = new Program { Value = 2 };
static Program program3 = new Program { Value = 3 };
pretty prints more lines
The second sample doesn't work simply because Value is a static member of Subclass.
C# syntax allows Superclass.Values, but eventually the compiled method call will be to the Subclass.Values getter. So the type Superclass is never actually touched. Superclass.SuperclassA1 on the other hand does touch the type and triggers the static initialization.
This is why C# doesn't really have implicit static initialization and you need composition frameworks like MEF and Unity.

Categories

Resources