c# program of Indexers - c#

there is an error in this program.can anyone fix that?
Error is :TempRecord already defines a member called 'this' with the same parameters value
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
private int[] d= new int[10]{4,5,5,4,4,43,2,2,5,3};
// To enable client code to validate input
// when accessing your indexer.
//public int Length
//{
// get { return temps.Length; }
//}
// Indexer declaration.
// If index is out of range, the temps array will throw the exception.
public float this[int index]
{
get
{
return temps[index];
}
set
{
temps[index] = value;
}
}
public int this[int index]//error:TempRecord already defines a member called 'this' with the same parameters value
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
// Use the indexer's set accessor
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
// Use the indexer's get accessor
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}

You have two members named this, that take the same parameters. That's not allowed in C# (or other .Net languages, as far as I'm aware).
You'd think you'd be able to do this if both members return different types, as yours do. But that would present the compiler with ambiguity. Which member would be called if you had code like this?
object x = tempRecord[3];
Make one or both indexers a method.

What you're trying to do is have 2 indexers with the same parameters and different return types. This is not legal in C#. You'll need to move at least one of them into a function
public int GetD(int index) {
return d[index];
}
public void SetD(int index, int value) {
d[index] = value;
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 65.9F, 62.1F, 59.2F, 57.5F }; private int[] d = new int[10] { 4, 5, 5, 4, 4, 43, 2, 2, 5, 3 };
public int Length //
{
get { return temps.Length; }
}
public float this[int index]
{
get { return temps[index]; }
set { temps[index] = value; }
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
If you are trying some concept similar to overloading of functions, I'd like to say it never works with just a change in return type. Similar is the case of data members, where you have tried to use this with the same arguments but different return types.
The best method would be however (even for readability sake) making separate functions for the exclusive events that are being performed above.
I deleted the second data member above, replace it with the something like the foll. I think you better use temprecord.d[index Value] to access & use the member d from main.
public int d[int index]
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}

Related

How do I populate my IEnumerable correctly? [duplicate]

This question already has answers here:
Difference between a List's Add and Append method?
(2 answers)
Closed 4 months ago.
https://dotnetfiddle.net/QHd0Rr#
I'm trying to populate a simple IEnumerable but I'm getting an error:
Unhandled exception. System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Program.Main()
Command terminated by signal 6
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var key1 = new WidgetA{Id = 1, Key = 52};
var key2 = new WidgetA{Id = 1, Key = 102};
var key3 = new WidgetA{Id = 1, Key = 152};
IEnumerable<WidgetA> list = Enumerable.Empty<WidgetA>();
list.Append(key1);
list.Append(key2);
list.Append(key3);
Console.WriteLine(list.ToList()[0]);
}
}
public class WidgetA
{
public int Id { get; set; }
public int Key { get; set; }
public string ValueToGet { get; set; }
}
Enumerable.Append<> is a lazy Linq function. If this is how you want to use it, you need to store the intermediate result:
IEnumerable<WidgetA> list = Enumerable.Empty<WidgetA>();
list = list.Append(key1);
list = list.Append(key2);
list = list.Append(key3);
While I really like (and upvoted) Blindy's answer and I think that it may better fit your need, here is an alternative with yield return:
public static void Main()
{
IEnumerable<int> list = DoStuff();
list.Dump();
}
public static IEnumerable<int> DoStuff()
{
yield return 0;
yield return 1;
// enter code here or whatever
yield return 2;
yield return 3;
yield return 4;
}

Is there a way to iterate through list of generic values in Unity/c#?

Is it possible to iterate through a several generic instances and do something with them?
public class Dynamic<T>
{
public T value;
public T defaultVal;
public void SetDefaultValue()
{
value = defaultVal;
}
}
Is it even possible to make it look something like this:
List<Dynamic<T>> dynamics = new List<Dynamics<T>>();
dynamics.Add(new Dynamic<float>());
dynamics.Add(new Dynamic<Vector2>());
///...
foreach (var item in dynamics)
{
item.SetDefaultValue();
}
And yeah, its probably useless at all since I have to manually insert these values in that list, but I really want to know if its even possible.
With the data model you have, in c# 2.0 there is no way to do what you want other than by declaring dynamics as a List<object> and using reflection:
List<object> dynamics = new List<object>();
dynamics.Add(new Dynamic<float>());
dynamics.Add(new Dynamic<Vector2>());
foreach (var item in dynamics)
{
item.GetType().GetMethod("SetDefaultValue").Invoke(item, null);
}
Not really recommended, since the performance will be poor, and you lose compile-time checking for correctness.
Instead, consider introducing a non-generic interface that allows accessing required members of Dynamic<T> in a non-generic manner:
public interface IDynamic
{
// Provide read-only access to the Value and DefaultValue as objects:
object Value { get; }
object DefaultValue { get; }
// Set the value to the default value:
void SetDefaultValue();
}
public class Dynamic<T> : IDynamic
{
public T value;
public T defaultVal;
public void SetDefaultValue()
{
value = defaultVal;
}
// Use explicit interface implementation because we don't want people to use the non-generic properties when working directly with a specific Dynamic<T>:
object IDynamic.Value { get { return value; } } // Note that if T is a struct the value will get boxed
object IDynamic.DefaultValue { get { return defaultVal; } } // Note that if T is a struct the value will get boxed
}
Now you will be able to do:
List<IDynamic> dynamics = new List<IDynamic>();
dynamics.Add(new Dynamic<float>());
dynamics.Add(new Dynamic<Vector2>());
foreach (var item in dynamics)
{
item.SetDefaultValue();
}
Extending dbc's answer, to have the properties of your class stored in a list to change them at once and by reference you need to wrap them into a class, for this case Dynamic<whatever>, because if you have primitive/value types, those will be copied into the list, and even the property values are changed looping through the list you would be changing the list copies and not the class properties themselves. Like so:
using System;
using System.Collections.Generic;
using UnityEngine;
public class GenericTrial2 : MonoBehaviour {
Dynamic<float> vertical = new Dynamic<float> { value = 17, defaultVal = 1 };
Dynamic<Vector2> run = new Dynamic<Vector2> { value = new Vector2(17, 17), defaultVal = Vector2.one };
Dynamic<Quaternion> rotation= new Dynamic<Quaternion> { value = new Quaternion(4,4,4,4), defaultVal = Quaternion.identity };
List<IDynamic> dynamics;
private void Start() {
dynamics = new List<IDynamic>();
dynamics.Add(vertical);
dynamics.Add(run);
dynamics.Add(rotation);
dynamics.ForEach(prop => { Debug.Log(prop.Value.ToString()); });
Debug.Log($"initValues: vertical: {vertical.value.ToString()}, " +
$"run: {run.value.ToString()}, rot: {rotation.value.ToString()} ");
}
void resetProps() {
foreach (var item in dynamics) {
item.SetDefaultValue();
}
dynamics.ForEach(prop => { Debug.Log(prop.Value.ToString()); });
}
private void Update() {
if (Input.GetKeyDown(KeyCode.Space)) {
resetProps();
Debug.Log($"after reset: vertical: {vertical.value.ToString()}, " +
$"run: {run.value.ToString()}, rot: {rotation.value.ToString()} ");
}
}
}
public interface IDynamic {
// Provide read-only access to the Value and DefaultValue as objects:
object Value { get; }
object DefaultValue { get; }
// Set the value to the default value:
void SetDefaultValue();
}
public class Dynamic<T> : IDynamic {
public T value;
public T defaultVal;
public void SetDefaultValue() {
value = defaultVal;
}
// Use explicit interface implementation because we don't want people to use the non-generic properties when working directly with a specific Dynamic<T>:
object IDynamic.Value { get { return value; } } // Note that if T is a struct the value will get boxed
object IDynamic.DefaultValue { get { return defaultVal; } } // Note that if T is a struct the value will get boxed
}
Output:
initValues: vertical: 17, run: (17.0, 17.0), rot: (4.0, 4.0, 4.0, 4.0)
after reset: vertical: 1, run: (1.0, 1.0), rot: (0.0, 0.0, 0.0, 1.0)

C# Triangle type calculation and area calculation

I am trying to solve or be pointed in the right direction. I am having difficulty determining where to place my Area formula in the Triangle Class (not the main). Area can only have a 'get' and not a 'set'.
Next issue is identifying the type of triangle based on the inputed side and if it is a 'right' triangle, appending the 'type' with '-right' for example (isosceles-right). I have an enum for the triangle types.
I'm not looking for the direct answer to solve this but rather some help and coaching to help better build my skills
Here is the class structure I have generated so far in C#, please keep in mind it is not complete.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleCheck;
namespace TriangleCheck
{
public class Triangle
{
private StringBuilder _ErrorMsg;
private int[] _Sides;
private const int _nSides = 3;
private int _Area;
public Triangle(int[] Sides)
{
//Track amunt of errors recieved.
int nErrors = 0;
//Make sure ErrorMsg is cleared
_ErrorMsg = new StringBuilder();
//Did I get _nSides? If not, append to ErrorMsg and throw exception
if(Sides.Length != _nSides)
{
_ErrorMsg.Append(string.Format("Expected {0} sides but recieved {1}", _nSides, Sides.Length));
nErrors += 1;
}
//Is each side positive? If not, append to ErrorMsg and throw exception
for (int i = 0; i < Sides.Length; i++)
{
if (Sides[i] <= 0)
{
_ErrorMsg.Append(string.Format("{0} side is not a postive integer", Sides[i]));
nErrors += 1;
}
}
//Set input from user to private property _Sides
_Sides = Sides;
_Area = Area;
}
public int Area
{
get { return _Area; }
private set
{
int parameter =
}
}
public string ErrorMsg
{
get
{ return ErrorMsg.ToString();}
}
public bool IsRight
{
get
{
return ;
}
}
public int Sides
{
get
{ return _Sides; }
set
{
if (value > 0)
{
_Sides = value;
}
else
throw new ArgumentOutOfRangeException("Value must be postive!");
}
}
public TriangleTypes TriangleTypes
{
get
{
throw new System.NotImplementedException();
}
set
{
}
}
public void ScaleUp(int[] ScaleFactor)
{
throw new System.NotImplementedException();
}
public override string ToString()
{
return "A Triangle with sides " + _Sides + " is Type: " + TriangleTypes + " with Area:" + Area;
}
}
}
You mention that you can't set the Area property... it looks like you're trying to enforce that by making a private set, but why not just exclude the set leaving it as a read-only property?
The Area formula could go a couple places; the key is that it is derived from the sides but only matters when someone asks for it. So you could reasonably:
Apply the formula and update internal state every time sides changes
Apply the formula and return the value every time someone does a get operation on Area
Remember the point of getter and setter being functions is that they could contain logic to execute (to fully update internal state in setter, or to calculate the value of a read-only derived property).
More sophisticated patterns exist if performance of the area calculation were very worrisome, but I wouldn't get into that at this point.
As for determining if the triangle is right... if it is, which side must be the hypotenuse? What relationship do you know between the length of the hypotenuse and the lengths of the other sides, if the triangle is right?
using System;
namespace ConsoleApp
{
class Program
{
static void Main()
{
var t = new Triangle(2, 3, 5);
//var Triangle = new Triangle(2); // won't compile as no Triangle constructor can be found that takes 1 integer
//var Triangle = new Triangle(2, 3, 5, 7); // won't compile as no Triangle constructor can be found that takes 4 integers
//var Triangle = new Triangle(2, -3, 5); // won't compile as the 2nd value is negative - and we've asked for unsigned for all 3 values
Console.WriteLine("The triangle ({0}, {1}, {2}) has an area of {3}.", t.A, t.B, t.C, t.area());
Console.ReadKey();
}
}
public class Triangle
{
public uint A { get; set; }
public uint B { get; set; }
public uint C { get; set; }
public Triangle(uint a, uint b, uint c)
{
this.A = a;
this.B = b;
this.C = c;
}
public uint area()
{
return A * B * C; // this needs fixing ...
}
}
}
Isn't this roughly what you are trying to achieve with your Triangle class - a way of stopping it being used incorrectly with too few or incorrect types of arguments. This one only allows 3 positive (uint) integers. Nothing else will comple - which is what you want. Sorry if I have misunderstood.

Creating a Session Helper Class that uses an array object C#

I am using a session helper class to track more than several variable. So far I have 30 that are needed from page to page, not all at once of course. I need to convert some of the values from single to array. The Session helper class I use is as follows. For brevity I have shown only two session variables we use for tracking tab index for two accordions.
using System;
using System.Globalization;
using System.Linq;
using System.Web;
public class SessionHelper
{
//Session variable constants
public const string AccordionTop = "#tabTop";
public const string AccordionBot = "#tabBot";
public static T Read<T>(string variable)
{
object value = HttpContext.Current.Session[variable];
if (value == null)
return default(T);
else
return ((T)value);
}
public static void Write(string variable, object value)
{
HttpContext.Current.Session[variable] = value;
}
public static int TabTop
{
get
{
return Read<int>(AccordionTop);
}
set
{
Write(AccordionTop, value);
}
}
public static int TabBot
{
get
{
return Read<int>(AccordionBot);
}
set
{
Write(AccordionBot, value);
}
}
}
So on each page I can work with variables easily as follows:
To Write:
SessionHelper.TabTop = 1; or SessionHelper.TabBot = 3
To Read:
If (SessionHelper.TabTop……….)
This all works fine. I now want to extend this to array values held in session. The array contains int, string and date time value.
For the array session object I have tried adding:
public class SessionHelper
{
public const string CompInfo = "CompAccInfo";
public static T ReadArray<T>(string variable)
{
object[] result = HttpContext.Current.Session[variable] as object[];
if (result == null)
{
return default(T);
//result = new object[30];
}
else
return ((T)(object)result);
}
public static void WriteArray(string variable, object[] value)
{
HttpContext.Current.Session[variable] = value;
}
public static object[] CompDetails
{
get
{
return ReadArray<object[]>(CompInfo);
}
set
{
WriteArray(CompInfo, value);
}
}
}
But then I get an “Object reference not set to…… error when I try to do this:
public void EGetCompanyInformation(MasterPage myMaster, int entityCode)
{
int prevEntity = 0;Using (sqlconnetiooo
.....
//I get values here this works fine
//Then:
sqlr = cmd.ExecuteReader();
sqlr.Read();
if (sqlr.HasRows)
{
//Calculate accounting period adjustment.
yearEndDiff = 12 - Convert.ToInt32(sqlr.GetDateTime(5).Month);
//Company Code.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
//Company Name.
SessionHelper.CompDetails[1] = sqlr.GetString(1);
//Currency Unit.
SessionHelper.CompDetails[2] = sqlr.GetString(2);
//Base Currency Code.
SessionHelper.CompDetails[3] = sqlr.GetString(3);
//Reporting Currency Code.
SessionHelper.CompDetails[4] = sqlr.GetString(4);
//Company Year End.
SessionHelper.CompDetails[5] = yearEndDiff;
//Country Code.
SessionHelper.CompDetails[6] = sqlr.GetString(6);
//Country Name.
SessionHelper.CompDetails[7] = sqlr.GetString(7);
//Base Currency Name.
SessionHelper.CompDetails[8] = sqlr.GetString(8);
//Report Currency Name.
SessionHelper.CompDetails[9] = sqlr.GetString(9);
//ClientID.
SessionHelper.CompDetails[10] = sqlr.GetInt32(10);
Other code here
}
}
It seems any SessionHelper.CompDetails[i] does not work : Error Object reference not set to an instance of an object.
What will happen if ReadArray will return default(T)? It will return null. Than access to any object by index inside the array will cause the exception you face.
It is not quite obvious what your code is intended to do.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
What do you want here? CompDetails itself should return an array. But you are trying to rewrite it immediately by some values.
If you want to access the CompDetails and rewrite it's objects than you have to instantiate it by
int n = 10;
SessionHelper.CompDetails = new CompDetails[n];
default(object[]) will always throw null. because the array of object is reference type and default value of any reference type is null. So accessing null value will get you Object reference not set to an instance of object.
You can change your old implementation like below:
public static T Read<T>(string variable, int arraySize=10)
{
object value = HttpContext.Current.Session[variable];
if(typeof(T).IsArray && value == null)
{
//array requires size I personally prefer to have
//differnt read method for array.
return ((T)Activator.CreateInstance(typeof(T),arraySize));
}
if(!typeof(T).IsValueType && value == null)
{
//if it is not value type you can return new instance.
return ((T)Activator.CreateInstance(typeof(T)));
}
else if (value == null)
return default(T);
else
return ((T)value);
}
And access SessionHelper as below:
var sessionarray = SessionHelper.Read<object[]>("myarray",15);
....
// then use that sessionarray here.
....
You have to instantiate the CompDetails array before you start assigning values to it.
if (sqlr.HasRows)
{
//Calculate accounting period adjustment.
yearEndDiff = 12 - Convert.ToInt32(sqlr.GetDateTime(5).Month);
// Instantiate array
SessionHelper.CompDetails = new object[11];
//Company Code.
SessionHelper.CompDetails[0] = sqlr.GetInt32(0);
// etc

Code snippet: create an "alias" for something else

I was looking for a similar way to create an alias for something else like its possible in C using preprocessor (this question is a bit similar, couldn't find anything useful there).
This is the problem: I've got a method that receives an array, but each position of the array has a specific meaning, like they where different parameters with specific names. What I want to do is to make my code easier to read (and write) by using those specific names, but, on the other hand, I don't want to create another method call (like in example 1) nor assign the array positions to new variables (example 2), because the performance is critical.
Example 1:
void OriginalMethodSignature(Type[] values)
{
SimplifiedMethod(values[0], values[1], ... values[n]);
}
void SimplifiedMethod(Type specificName1, Type specificName2, ... Type specificNameN)
{
// simple implementation using specific names instead of values[n]
}
Example 2:
void OriginalMethodSignature(Type[] values)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
// simple implementation using specific names instead of values[n]
}
I cannot change the method signature because its used in a dellegate, the Type is fixed.
The next example is a bit better, but still not optimum:
void OriginalMethodSignature(Type[] values)
{
// implementation using values[specificName1] ... values [specificNameN]
}
const int specificName1 = 0;
const int specificName2 = 1;
...
const int specificNameN = n-1;
Is there any way to create an snippet for this purpose? If yes, how would it be?
There isn't any built in way to do what you wan't, because you shouldn't really be doing it at all. You should be using an object with properties instead of an array.
Anyway, you can make an object that encapsulates the array, so that the properties use the array as storage:
public class NamedObject {
private Type[] _values;
public NamedObject(Type[] values) {
_values = values;
}
public SpecificName1 { get { return _values[0]; } set { _values[0] = value; } }
public SpecificName2 { get { return _values[1]; } set { _values[1] = value; } }
public SpecificName3 { get { return _values[2]; } set { _values[2] = value; } }
public SpecificName4 { get { return _values[3]; } set { _values[3] = value; } }
public SpecificName5 { get { return _values[4]; } set { _values[4] = value; } }
public SpecificName6 { get { return _values[5]; } set { _values[5] = value; } }
}
Now you can use the object to access the array:
void OriginalMethodSignature(Type[] values) {
NamedObject obj = new NamedObject(values);
// get a value
Type x = obj.SpecificName4;
// set a value
obj.SpecificName2 = x;
}
Create a dedicated class or struct, and parse the array into it.
public class MyClassOfStuff
{
Type SpecificName1 {get;set;}
Type SpecificName2 {get;set;}
public static MyClassOfStuff Parse(Type[] value)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
}
}
void OriginalMethodSignature(Type[] values)
{
var mystuff = MyClassOfStuff.Parse(values);
}

Categories