Cannot Add to generic list - c#

Firstly I apologise for the oversimplification, but I have this issue which is driving me crazy. It should work - it's simple code, nothing fancy.......
I have this object
public class Stuff
{
private int intStuff;
private string strStuff;
public Stuff(int StuffID, string Stuff)
{
intStuff = StuffID;
strStuff = Stuff;
}
public int StuffID
{
get { return intStuff; }
set { intStuff = value; }
}
public string Stuff
{
get{return strStuff;}
set{strStuff=value;}
}
}
Which is used in this class:
public class StuffandThings
{
private List<Stuff> lstMyStuff;
public List<Stuff> StuffList
{
set { lstMyStuff = value; }
get { return lstMyStuff; }
}
public StuffandThings()
{
lstMyStuff = new List<Stuff>();
}
}
Which is declared as a static in Global.asax <<<< this may be important
public static StuffAndThings MyStuff;
protected void Application_Start(object sender, EventArgs e)
{
MyStuff = new StuffandThings();
}
And when I use it in code:
foreach (string strStuff in lstStuff)
{
objStuff = new Stuff(intStuff,strStuff);
Global.MyStuff.StuffList.Add(objStuff);
}
It compiles and I can run in debug (it's a WCF Web service), my variables (intStuff and lstStuff) are all valid.but when I click on Service.svc in the browser I get the following error.
CS1502: The best overloaded method match for 'System.Collections.Generic.List.Add(Stuff)' has some invalid arguments
I don't think I can see the wood for the trees with this one and the interwebs have been no help.
Aso, all my other objects and functions in the global object are fine - hashtables mostly, and my code ran until I tried to add this functionality. I would use a hashtable but I would need the key to not be unique;
Any Ideas, please?
Thanks
P

You should declare the type of objStuff inside the loop. Always declare variables inside the smallest scope you can:
Stuff objStuff = new Stuff(intStuff,strStuff);
Global.MyStuff.StuffList.Add(objStuff);
If this fails to compile because objStuff is already in use in the parent scope then find a new name - objStuff2 for example, then everything should work.
Where is objStuff declared in your code? You might be picking up the declaration of something else that also happens to be called objStuff but is actually unrelated.

Related

Argument Labels in C#

Is there a way in C# to be able to refer to a a parameter by both an internal and external name (in Swift this is known as argument labels/parameters)?
What I mean is suppose I have the following:
public static class Sport
{
public static void Print(int id sportID)
{
Console.Out.WriteLine(sportID);
}
}
public static void main()
{
Sport.Print(id: 123);
}
Internally, I refer to the id as sportID, but externally, the parameter is known as id.
A little late to the game, but I was looking for something like this as well. It is not exactly what the OP is after, but I think it is close enough.
The parameter names that are set when you declare the methods can be called when calling the method.
Declaring the method:
static string[] Roster(int numberOfDaysOff, int daysOfStartOnDay) {
// Method logic with the set names
}
Calling the method:
Roster(numberOfDaysOff: daysOff,daysOfStartOnDay: startDay);
Hope this helps future readers :-)
public static void Print(int id)
{
int sportId = id;
Console.Out.WriteLine(sportID);
}
?
There's no language implicit way of aliasing the var that I'm aware of, but you can rename it by passing it to another, private function that calls it sportId, or you can assign it to a new var yourself in the function.
Not sure why you'd want to do this but here is one way:
class Parameters
{
private int _id;
public int ID
{
get { return _id;}
set { _id = value;}
}
public int SportID
{
get { return _id;}
set { _id = value;}
}
}

How to handle nameof(this) to report class name

I'd like to use the following C#6 code
var joe = new Self();
Console.WriteLine(joe);
... and get the following output:
joe
The following attempt
class Self {
public string Name { get; set; } = nameof(this);
public override string ToString() {
return Name;
}
}
fails as nameof cannot be applied to this. Is it there a workaround for this problem?
EDIT. The scenario I'm working with assures that no two references point to the same Self object.
No, nameof is designed to refer to the compile-time name of the member you're referring to. If you want an object to have a Name property as part of its state, that is independent of how you get to the Name property - as Frédéric Hamidi says, there could be multiple variables (or none) referring to the same object. Basically you need to differentiate between an object and a variable which happens to refer to that object.
However, if you have a constructor to specify the name, you could then use a couple of tricks to make it easier to get the right name:
class Self
{
public string Name { get; }
public Self([CallerMemberName] string name = null)
{
this.Name = name;
}
}
Then:
class Foo
{
private Self me = new Self(); // Equivalent to new Self("me")
public void SomeMethod()
{
// Can't use the default here, as it would be "SomeMethod".
// But we can use nameof...
var joe = new Self(nameof(joe));
}
}
Maybe you can use the following method:
class Self
{
public override string ToString()
{
return this.GetType().Name;
}
}
You can simply use nameof on the variable itself:
Console.WriteLine(nameof(joe));
Here's a working example using the current Roslyn version
The idea for nameof is to make things type safe for specifying program elements during runtime but with compile time type safety checking.
One should atomize what one wants to display. For example in my error messages I include the pertinent information of the class name and the method as such and its checked, so if I change any of the names they are caught as a compile time error:
class Operation
{
public void Execute()
{
try { ... }
catch (Exception ex)
{
Console.Writeline($"{nameof(Operation)}.{nameof(Execute)} has encountered exception:{Environment.NewLine}{Environment.NewLine}{ex.Message}" );
}
}
}
Output
Operation.Excecute has exception:
...
With that said you should override ToString() and report the class name as such
public override string ToString() { return nameof(Self); }
I usually create an internal constant for it when dealing with long class names:
private const string SomeConst = nameof(Self);
Then you can use that in your code:
Console.WriteLine(SomeConst);

Keep my list/dictionary as globally accessible

Ok... I'm trying to understand this whole object oriented programming but I keep ending up in a dead end. ;)
I'm trying to store or rather will store a great deal of data with using classes as I should. I want to store planetary data by using a class with several properties, I will then save these into a list.
My problem is that I don't know how to make this list globally accessible, it is only accessible in the instance where it is created.
Some sample code from my test environment below.
OrbitalBodies.cs
class OrbitalBodies
{
public int BodyID { get; set; }
public string BodyName { get; set; }
public int BodySize { get; set; }
public int BodyX { get; set; }
public int BodyY { get; set; }
}
From1.cs
public void button1_Click(object sender, EventArgs e)
{
var bodies0 = new OrbitalBodies();
var orbitalList = new List<OrbitalBodies>();
bodies0.BodyID = 4;
bodies0.BodyName = "Earth";
bodies0.BodySize = 125;
bodies0.BodyX = -450;
bodies0.BodyY = 75;
orbitalList.Add(bodies0);
bodies0.BodyID = 0;
bodies0.BodyName = "Sol";
bodies0.BodySize = 500;
bodies0.BodyX = 0;
bodies0.BodyY = 0;
orbitalList.Add(bodies0);
//var orbitalDic = new Dictionary<int, OrbitalBodies>();
MessageBox.Show("Planetary body name: " + Convert.ToString(orbitalList.Count()));
}
I have spent a couple of hours looking up my problem here and other places but I don't know how I can access the information I put into the list other than in that single instance. My real application will have tens of thousands of orbital bodies and many other data that must be accessible throughout many forms and perhaps even other classes.
Some help would be appreciated, what is the best solution? Do it completely differently?!?
You don't want static members or singletons (both of which cause more problems than they solve), you need Dependency Injection.
Outside of your form create the List, pass it into the forms constructor. Everywhere you need to use the list, pass the instance you have from the form.
This way there is only one list, everywhere that needs the list is passed a list (that just happens to be the same list).
If in time you realize you actually need to model two different systems, you just create two different lists, and pass them to two different forms, everything keeps working and you don't need to go back through your code removing references to static members.
Honestly, this is completely doable without going to the dark side and perpetuating the evil that is static/global variables.
NB Why static variables are considered evil
Use design pattern Singleton.
public class Globals
{
private List<OrbitalBodies>() orbiralList;
private static Globals instance;
private Globals()
{
this.orbiralList = new List<OrbitalBodies>();
this.instance = NULL;
}
public static List<OrbitalBodies>() GetOrbitalBodies()
{
if (instance == null) instance = new Globals();
return instance.orbitaList;
}
}
Then everywhere in your code, when you will need orbitalList call
Globals.GetOrbitalBodies().<do whatever with your list>
Try not to use static classes, because they are mess in term of OO design.
Make OrbitalList a property:
public List<OrbitalBodies> OrbitalList {get;set;}
public void button1_Click(object sender, EventArgs e)
{
var bodies0 = new OrbitalBodies();
bodies0.BodyID = 4;
bodies0.BodyName = "Earth";
bodies0.BodySize = 125;
bodies0.BodyX = -450;
bodies0.BodyY = 75;
OrbitalList.Add(bodies0);
//...
}
//Then you can do:
doSomething(myForm.OrbitalList[0]);
If you just want to access your list within the "Form1" class, just declare it as a private member out of a function:
private List<OrbitalBodies> _orbitalList;
and then instanciate it into your "button1_Click" method.
If you want to access your list in all your classes, I suggest you make it static :
public class NewClass
{
public static List<OrbitalBodies> OrbitalList {get; set;};
}
and you call it like this
NewClass.OrbitalList;
Hope that helps.

Following the DRY principle in ASP.NET

I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.

How can I override get and set methods for all properties in a class?

I have got several classes looking like the one below, and I need to do some checks in the get method and custom set methods. Adding the code in each get and set method makes everything look really messed up.
Is there a way I can override the get and set methods for all properties in an entire class?
public class Test
{
private DataRow _dr;
public Test()
{
_dr = GetData();
}
public string Name
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)] = value;
}
}
public string Description
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)] = value;
}
}
public string DescriptionUrl
{
get { return _dr[MethodBase.GetCurrentMethod().Name.Substring(4)].ToString(); }
set
{
VerifyAccess(MethodBase.GetCurrentMethod().Name.Substring(4), this.GetType().Name);
_dr[MethodBase.GetCurrentMethod().Name.Substring(4)]= value;
}
}
private void VerifyAccess(string propertyname, string classname)
{
//some code to verify that the current user has access to update the property
//Throw exception
}
private DataRow GetData()
{
//Some code to pull the data from the database
}
}
I think what you need is a Proxy on your class, read about Proxy Pattern and Dynamic Proxies
Not directly, there isn't a way to do it with just a compiler. You'd have to generate your entire binary file, then post-process it with some external tool.
This post describes a somewhat similar issue; I hope it helps.
There's a variety of ways to do it.
One would be to create a proxy class (mentioned before), but that would require a lot of refactoring on your behalf.
Another way is with aspects. These do exactly what you're after (insert code based on a pre-requisite.. i.e. all get methods in a class that inherit from x). I ran into a similar problem (actually the exact same problem - checking for security on method calls), and couldn't find cheap/free aspect software that fulfilled my needs.
So, I decided to use Mono-Cecil to inject code before function calls.
If you're interested (it gets a bit messy dealing with IL codes) I can post an old copy of the source
You should extract common code to separate get/set methods, after that you'll be able to add common logic to your properties. By the way, I would do such extraction anyway to avoid copy/paste in the code.
Smth like this:
public string Name
{
get { return GetProperty(MethodBase.GetCurrentMethod()); }
set
{
SetProperty(MethodBase.GetCurrentMethod(), value);
}
}
private string GetProperty(MethodBase method)
{
return _dr[method.Name.Substring(4)].ToString();
}
private void SetProperty(MethodBase method, string value)
{
string methodName = method.Name.Substring(4);
VerifyAccess(methodName , this.GetType().Name);
_dr[methodName] = value;
}
This can be done with indirect value access, e.g. obj.PropA.Value = obj.PropB.Value + 1 -- you can even keep strong typing information. It can be implemented with either attributes or direct-instantiation.
// attribute -- bind later in central spot with annotation application
[MyCustomProp(4)] CustProp<int> Age;
// direct -- explicit binding, could also post-process dynamically
CustProp<int> Age = new CustProp<int>(4, this);
Alternatively, perhaps using a template system such as TT4 may be a viable approach.
However, don't forget "KISS" :-)
I would love for someone to give a better answer for this.
I'm looking for an answer now… best idea I have had would be to define all the properties you want to have be validated as a generic class. For example:
public class Foo {
public String Name {
get{ return _Name.value; }
set{ _Name.value = value; }
}
private Proxy<String> _Name;
static void main(String[] args) {
Foo f = new Foo();
//will go through the logic in Proxy.
f.Name = "test";
String s = f.Name;
}
}
public class Proxy<T> {
public T value {
get {
//logic here
return _this;
} set {
//logic here
_this = value;
}
}
private T _this;
}

Categories

Resources