Need to check dictionary in another method, or make dictionary global - c#

I need to see if a dropdown box has selected a key out of a dictionary. The dictionary is in another method (I believe its called a method). I've been searching how to make the dictionary global, but i can't figure out how to do it. Maybe there is a better way?
Thanks for any help, I wrote some code to show what I'm trying to accomplish below.
public void Dictionary()
{
var names = new Dictionary<string, double[]>();
names.Add("Kevin", new[] { 74.5, 6.35});
names.Add("Rob", new[] { 2.5, 9.46});
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var kvp in names)
{
if combobox.Text == kvp.Key
{
solution = true;
}
}
}

Another way you could handle this would be to return the Dictionary.
public Dictionary GetDictionary()
{
var names = new Dictionary<string, double[]>();
names.Add("Kevin", new[] { 74.5, 6.35});
names.Add("Rob", new[] { 2.5, 9.46});
return names;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var kvp in GetDictionary())
{
if (combobox.Text == kvp.Key)
{
solution = true;
}
}
}

Making the method public is what makes it accessible globally. There are a couple of missing pieces: the method itself is missing a return type, and it needs to be directly called from the combobox1_SelectedIndexChanged method.
It is best practice to not use a reserved name from the .NET framework in custom code - here I have changed the method name to GetDropdownChoices, added a return type, and then called the method outside of the foreach loop. For perfomance optimization, one suggestion is to use the .ContainsKey method instead looping through each item in a dictionary.
public Dictionary<string, double[]> GetDropdownChoices()
{
var names = new Dictionary<string, double[]>();
names.Add("Kevin", new[] { 74.5, 6.35});
names.Add("Rob", new[] { 2.5, 9.46});
return names;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var choices = GetDropdownChoices();
if (choices.ContainsKey(combobox.Text))
{
solution = true;
}
}

public class Foo
{
private readonly Dictionary<string, double[]> _names;
public Foo()
{
_names = new Dictionary<string, double[]>();
}
public void Dictionary() // note: this is just name taken from initial question
{
_names.Add("Kevin", new[] { 74.5, 6.35 });
_names.Add("Rob", new[] { 2.5, 9.46 });
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var kvp in _names)
{
if (combobox.Text == kvp.Key) // assuming you have already a declared "combobox" member
{
solution = true;
}
}
}
}

Related

How to make a list `global` in c#?

Firstly, most of my experience with coding is through python hence my use of global
I have a list and I want to be able to search the list and find all words that are of x length. My main issue is not knowing how to call a function from inside an event listener.
So myList is generated inside of my function functionOne, I am then wanting to use this list inside functionTwo and then finally I want to call it when buttonOne is clicked. E.g buttonOne_Click ....
This is what I have so far for functionOne
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
List<string> remove = convertLower.Distinct().ToList();
return remove;
}
functionTwo
public List<string> length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach(string item in myList)
{
if(item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
And finally my event listener
private void button_Click(object sender, EventArgs e)
{
length(remove);
}
NOTE: remove is the list I am trying to work with
But there is no output with this code because I get an error saying remove doesn't exist in this context, I'm unsure how I make this list global
Put all the functions in the same class and use noDup on your list instance.
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
List<string> remove = convertLower.Distinct().ToList();
return remove;
}
public void length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach(string item in myList)
{
if(item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
private void button_Click(object sender, EventArgs e)
{
var remove = noDup(yourInputList);
length(remove);
}
We'll here's the general idea how to achieve this in a win forms c# application.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private List<string> _remove;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
length(_remove);
}
public List<string> noDup(List<string> myList)
{
var convert = myList.ConvertAll(i => i.ToLower());
_remove = convertLower.Distinct().ToList();
}
public List<string> length(List<string> myList)
{
int i = int.Parse(lengthSearch.Text);
List<string> temp = new List<string>();
foreach (string item in myList)
{
if (item.Length == i)
{
temp.Add(item);
}
}
searchResult.Text = string.Join(",", temp);
}
}
}
Mind this doesn't build since I just used your code. For example the length method should return a List<string> but it doesn't. You would probably want to change the list that's passed in and then return it, or mutate the class level variable _remove.
Either way the event handler button1_Click needs to work with a class level variable (such as _remove that I added) or call a method that will return the list (as is present in the other anwser by Zbigniew.)

Dynamic arguments for events [duplicate]

Let's say I want to pass some extra data when assigning an event handler. Consider the following code:
private void setup(string someData)
{
Object.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
// need someData here!!!
}
How would I go about getting someData into my evHandler method?
private void setup(string someData)
{
Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
// need someData here!!!
}
I had a hard time figuring out #spender's example above especially with: Object.assignHandler((sender) => evHandler(sender,someData)); because there's no such thing as Object.assignHandler in the literal sense. So I did a little more Googling and found this example. The answer by Peter Duniho was the one that clicked in my head (this is not my work):
snip
The usual approach is to use an anonymous method with an event handler
that has your modified signature. For example:
void Onbutton_click(object sender, EventArgs e, int i) { ... }
button.Click += delegate(object sender, EventArgs e)
{ Onbutton_click(sender, e, 172); };
Of course, you don't have to pass in 172, or even make the third parameter
an int. :)
/snip
Using that example I was able to pass in two custom ComboBoxItem objects to a Timer.Elapsed event using lambda notation:
simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);
and then into it's handler:
static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
{
Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
}
This isn't any new code from the examples above, but it does demonstrate how to interpret them. Hopefully someone like me finds it instructive & useful so they don't spend hours trying to understand the concept like I did.
This code works in my project (except for a non-thread-safe exception with the ComboBoxItem objects that I don't believe changes how the example works). I'm figuring that out now.
Captured variables:
private void setup(string someData)
{
Object.assignHandler((sender,args) => {
evHandler(sender, someData);
});
}
public void evHandler(Object sender, string someData)
{
// use someData here
}
Or (C# 2.0 alternative):
Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
evHandler(sender, someData);
});
you can try doing this:
string yourObject;
theClassWithTheEvent.myEvent += (sender, model) =>
{
yourObject = "somthing";
}
My question that was similar was marked a duplicate so thought I'd add an answer here since it won't let me on my question.
class Program
{
delegate void ComponentEventHandler(params dynamic[] args);
event ComponentEventHandler onTest;
static void Main(string[] args)
{
Program prg = new Program();
// can be bound to event and called that way
prg.onTest += prg.Test;
prg.onTest.Invoke("What", 5, 12.0);
Console.ReadKey();
}
public void Test(params dynamic[] values)
{
// assign our params to variables
string name = values[0];
int age = values[1];
double value = values[2];
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(value);
}
}
Well, the simplest method id to make someData a member variable like so:
public class MyClass
{
private string _eventData;
private void setup(string someData)
{
_eventData = someData;
Object.assignHandler(evHandler);
}
public void evHandler()
{
// do something with _eventData here
}
}
I'm not sure that's the best way to do it, but it really depends on the event type, the object, etc.
You could create a custom object having additional properties based on Object:
class CustomObject : Object
{
public string SomeData;
}
private void setup(string someData)
{
CustomObject customObject = new CustomObject { SomeData = someData };
CustomObject.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
string someData = ((CustomObject)sender).SomeData;
}
If the data should not be changed anymore after initialization, you could also add a custom constructor, for example.
Here is my one-line solution that pass extra parameters to a timer handler.
private void OnFailed(uint errorCode, string message)
{
ThreadPoolTimer.CreateTimer((timer) => {
UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
}, System.TimeSpan.FromMilliseconds(100));
}
This solution offers a way to pass extra parameters to an event handler while still allowing to unsubscibe:
Within the Subscribe() function of my example I create an Action that invokes a lambda function that supplies my event handler with the event args and my extra parameter. I then store this Action in a dictionary. When I want to unsubscribe, I can use the stored Actions to do so.
This works, I read the length of listeners before and after unsubscribing and it did decrease - you can unsubscribe again without problems.
public class Player
{
public Action<JumpInfo> OnJump;
}
public class PlayerJumpListener
{
public List<Player> MyPlayerList;
private Dictionary<Player, Action<JumpInfo>> _jumpActionsByPlayer = new Dictionary<Player, Action<JumpInfo>>();
private void Subscribe()
{
foreach (Player player in MyPlayerList)
{
Action<JumpInfo> playerJumpAction = (jumpInfo) => HandlePlayerJump(jumpInfo, player);
player.OnJump += playerJumpAction;
_jumpActionsByPlayer.Add(player, playerJumpAction);
}
}
private void Unsubscibe()
{
foreach (KeyValuePair<Player, Action<JumpInfo>> kvp in _jumpActionsByPlayer)
{
kvp.Key.OnJump -= kvp.Value;
}
}
private void HandlePlayerJump(JumpInfo jumpInfo, Player player)
{
// player jumped
}
}
I scoured the internet before a coworker kindly helped me, and boy I felt dumb. Brackets is the solution for the EventHandler.
Ex.
event EventHandler<(int, bool)> EventName;
and then pick it up with:
private void Delegate_EventName(object sender, (int, bool) e)
you can then access the info:
var temp = e.Item1;<br>
var temp2 = e.Item2;<br>
or you can add names as you would expect for parameters and call them via e:
private void Delegate_EventName(object sender, (int num, bool val) e)
you can then access the info:
var temp = e.num;
var temp2 = e.val;

Overriding methods of form controls [duplicate]

Let's say I want to pass some extra data when assigning an event handler. Consider the following code:
private void setup(string someData)
{
Object.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
// need someData here!!!
}
How would I go about getting someData into my evHandler method?
private void setup(string someData)
{
Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
// need someData here!!!
}
I had a hard time figuring out #spender's example above especially with: Object.assignHandler((sender) => evHandler(sender,someData)); because there's no such thing as Object.assignHandler in the literal sense. So I did a little more Googling and found this example. The answer by Peter Duniho was the one that clicked in my head (this is not my work):
snip
The usual approach is to use an anonymous method with an event handler
that has your modified signature. For example:
void Onbutton_click(object sender, EventArgs e, int i) { ... }
button.Click += delegate(object sender, EventArgs e)
{ Onbutton_click(sender, e, 172); };
Of course, you don't have to pass in 172, or even make the third parameter
an int. :)
/snip
Using that example I was able to pass in two custom ComboBoxItem objects to a Timer.Elapsed event using lambda notation:
simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);
and then into it's handler:
static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
{
Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
}
This isn't any new code from the examples above, but it does demonstrate how to interpret them. Hopefully someone like me finds it instructive & useful so they don't spend hours trying to understand the concept like I did.
This code works in my project (except for a non-thread-safe exception with the ComboBoxItem objects that I don't believe changes how the example works). I'm figuring that out now.
Captured variables:
private void setup(string someData)
{
Object.assignHandler((sender,args) => {
evHandler(sender, someData);
});
}
public void evHandler(Object sender, string someData)
{
// use someData here
}
Or (C# 2.0 alternative):
Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
evHandler(sender, someData);
});
you can try doing this:
string yourObject;
theClassWithTheEvent.myEvent += (sender, model) =>
{
yourObject = "somthing";
}
My question that was similar was marked a duplicate so thought I'd add an answer here since it won't let me on my question.
class Program
{
delegate void ComponentEventHandler(params dynamic[] args);
event ComponentEventHandler onTest;
static void Main(string[] args)
{
Program prg = new Program();
// can be bound to event and called that way
prg.onTest += prg.Test;
prg.onTest.Invoke("What", 5, 12.0);
Console.ReadKey();
}
public void Test(params dynamic[] values)
{
// assign our params to variables
string name = values[0];
int age = values[1];
double value = values[2];
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(value);
}
}
Well, the simplest method id to make someData a member variable like so:
public class MyClass
{
private string _eventData;
private void setup(string someData)
{
_eventData = someData;
Object.assignHandler(evHandler);
}
public void evHandler()
{
// do something with _eventData here
}
}
I'm not sure that's the best way to do it, but it really depends on the event type, the object, etc.
You could create a custom object having additional properties based on Object:
class CustomObject : Object
{
public string SomeData;
}
private void setup(string someData)
{
CustomObject customObject = new CustomObject { SomeData = someData };
CustomObject.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
string someData = ((CustomObject)sender).SomeData;
}
If the data should not be changed anymore after initialization, you could also add a custom constructor, for example.
Here is my one-line solution that pass extra parameters to a timer handler.
private void OnFailed(uint errorCode, string message)
{
ThreadPoolTimer.CreateTimer((timer) => {
UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
}, System.TimeSpan.FromMilliseconds(100));
}
This solution offers a way to pass extra parameters to an event handler while still allowing to unsubscibe:
Within the Subscribe() function of my example I create an Action that invokes a lambda function that supplies my event handler with the event args and my extra parameter. I then store this Action in a dictionary. When I want to unsubscribe, I can use the stored Actions to do so.
This works, I read the length of listeners before and after unsubscribing and it did decrease - you can unsubscribe again without problems.
public class Player
{
public Action<JumpInfo> OnJump;
}
public class PlayerJumpListener
{
public List<Player> MyPlayerList;
private Dictionary<Player, Action<JumpInfo>> _jumpActionsByPlayer = new Dictionary<Player, Action<JumpInfo>>();
private void Subscribe()
{
foreach (Player player in MyPlayerList)
{
Action<JumpInfo> playerJumpAction = (jumpInfo) => HandlePlayerJump(jumpInfo, player);
player.OnJump += playerJumpAction;
_jumpActionsByPlayer.Add(player, playerJumpAction);
}
}
private void Unsubscibe()
{
foreach (KeyValuePair<Player, Action<JumpInfo>> kvp in _jumpActionsByPlayer)
{
kvp.Key.OnJump -= kvp.Value;
}
}
private void HandlePlayerJump(JumpInfo jumpInfo, Player player)
{
// player jumped
}
}
I scoured the internet before a coworker kindly helped me, and boy I felt dumb. Brackets is the solution for the EventHandler.
Ex.
event EventHandler<(int, bool)> EventName;
and then pick it up with:
private void Delegate_EventName(object sender, (int, bool) e)
you can then access the info:
var temp = e.Item1;<br>
var temp2 = e.Item2;<br>
or you can add names as you would expect for parameters and call them via e:
private void Delegate_EventName(object sender, (int num, bool val) e)
you can then access the info:
var temp = e.num;
var temp2 = e.val;

C# return Dictionary

Im trying to write a method that returns a Dictionary, but it seems like it ends up being empty.
Can you find out what I am doing wrong ?
When I click the button to search for a Key, It gives Error: Dictionary contains no Keys.
class Person
{
public int PersNr { get; set; }
public string Name { get; set; }
public string BioPappa { get; set; }
public Adress Adress { get; set; }
public static Dictionary<int, Person> Metod()
{
var dict = new Dictionary<int, Person>();
dict.Add(870603, new Person
{
Name = "Jonathan",
PersNr = 870603,
BioPappa = "Jarmo",
Adress = new Adress
{
Land = "Sverige",
PostNr = 73249,
Stad = "Arboga"
}
});
dict.Add(840615, new Person
{
Name = "Lina",
PersNr = 840615,
BioPappa = "Erik"
});
return dict;
}
namespace WindowsFormsApplication148
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Person.Metod();
var person = myDic[int.Parse(textBoxSok.Text)];
listBox1.Items.Add(person.Name);
listBox1.Items.Add(person.PersNr);
listBox1.Items.Add(person.BioPappa);
listBox1.Items.Add(person.Adress.Stad);
listBox1.Items.Add(person.Adress.PostNr);
listBox1.Items.Add(person.Adress.Land);
}
When you call your method (Please use a more meaningful and less confusing name) you need to receive the result of its work
private void button1_Click(object sender, EventArgs e)
{
Dictionary<int, Person> myDic = person.Metod();
var person = myDic[int.Parse(textBoxSok.Text)];
.......
However you haven't shown all of your code because, as shown in your question the code doesn't compile. I suppose that you have somewhere declared AND INITIALIZED the variable myDic because you need to use it in different parts of your forms. This is somewhat to be analyzed better because the call to Metod reinitializes the local variable myDic to the Dictionary returned by the method call.
private void button1_Click(object sender, EventArgs e)
{
//WRONG
Person.Metod();
You execute a method but do not assign the result to anything.

C# Event Argument passing

Ok, so I have a question regarding the EventArgs that can be passed when an event is triggered. I am designing a small, basic search engine and have a class called Query that contains a method Search. When this method is called, I want to trigger an event which will pass the results to be storred in a variety of cache class instances (SizeBoundedCache and TimeBoundedCache). So I thought the best way to do this would be to use an event.
The delegate is declared like this ->
public delegate void CacheStoreDelegate(object sender, EventArgs e);
The rest of the code within the Query class relevant to this question is here (uses Linq) ->
public event CacheStoreDelegate AddToCache;
public virtual void OnQuery (EventArgs e)
{
if(AddToCache != null)
AddToCache(this, e);
}
public Query()
{
}
public Query(string queryString, OOP5.Provided.QueryOperator op)
{
//Access and set the terms array
this.Terms = OOP5.Provided.QueryUtils.GetTermsFromString(queryString);
this.Operator = op;
}
public static IEnumerable<string> Search (this SearchCore s, IQuery q)
{
// Accept a query and return IEnumerable<string> of
// all document IDs matching that query
if (q.Operator == QueryOperator.Any)
{
var GetAnyMatch = from single_query in q.Terms
group s.Search(single_query)
by s.documents.Keys
into results
where results.Count >= 1
select results[0];
this.OnQuery(GetAnyMatch);
return GetAnyMatch;
}
if (q.Operator == QueryOperator.All)
{
var GetAllMatch = from single_query in q.Terms
group s.Search(single_query)
by s.documents.Keys
into results
where results.Count >= q.Terms.Lengthselect results[0];
this.OnQuery(GetAllMatch);
return GetAllMatch;
}
}
All the cache classes will be notified whenever a search is called and I also need thme to receive the results.
Thanks so much in advance for the help. Also, if there is a more elegant way to do this that I am not thinking of, please chime in. Cheers!
You could create your own EventArgs implementation:
class QueryResultEventArgs : EventArgs
{
public IEnumerable<string> Results { get; private set; }
public QueryResultEventArgs(IEnumerable<string> results)
{
Results = results;
}
}
...
public delegate void CacheStoreDelegate(object sender, QueryResultEventArgs e);
...
this.OnQuery(new QueryResultEventArgs(GetAnyMatch));
Make a class of type CacheStoreEventArgs deriving from eventargs
public class CacheStoreEventArgs:eventargs
{
private IEnumerable<string> Data;//List<string> better
public IEnumerable<string> data
{
get { return Data; }
set { this.Data = value; }
}
public CacheStoreEventArgs(IEnumerable<string> NewData)
{
this.data = NewData;
}
}
then declare the event(use predefined generic one,so no need to declare one)
public event EventHandler<CacheStoreEventArgs> AddToCache;
inside your method search you call your method "On...."
public static IEnumerable<string> Search (this SearchCore s, IQuery q)
{
//after you get query result
CacheStoreEventArgs cs = new CacheStoreEventArgs(queryresultvariablehere);
//and call your method now with the instance of your derived eventargs class
OnQuery(cs);
}
public virtual void OnQuery (CacheStoreEventArgs e)
{
try
{
EventHandler<CacheStoreEventArgs> temp = AddToCache
if( temp != null)
temp(this,e);
}
catch(Exception ex)
{
//exception handling
}
}

Categories

Resources