C# struct treated like a Reference - c#

I have struct called KinectBody and i assign an object of this type which is in a class called BodyContributor to a field in a class called KinectSystemComponent. Now every time the field in the BodyContributor changes, the field in my KinectSystemComponent changes too just like it was a reference type. How does that happen. Below are the involved classes:
using System.Collections.Generic;
namespace Alpaca.Systems.Kinect
{
public class KinectSystemComponent : KinectComponent, Alpaca.Systems.Events.IEventHandler<UserTrackingEvent>
{
private static Dictionary<ulong, KinectBody> assignedBodies = new Dictionary<ulong, KinectBody>();
BodyContributor contributor;
public static bool useSystemComponents = true;
public static bool IsBodyAlreadyAssigned(KinectBody body)
{
return assignedBodies.ContainsKey(body.trackingID);
}
public override void Initialize()
{
contributor = BodySource.Instance.contributor;
this.ComponentType = ComponentType.SystemComponent;
}
public override void OnUpdate()
{
//if(useSystemComponents)
//{
// if(!Body.isTracked)
// {
// KinectBody[] bodies = contributor.GetBodies();
// for(int i = 0; i < bodies.Length; i++)
// {
// KinectBody currentBody = bodies[i];
// if(currentBody.isTracked)
// {
// if(!IsBodyAlreadyAssigned(currentBody))
// {
// this.Body = currentBody;
// }
// }
// }
// }
// else
// {
// Body = contributor.GetBodyByID(Body.trackingID);
// }
//}
//else if(Body.isTracked)
//{
// Body = new KinectBody();
//}
}
public void HandleEvent(UserTrackingEvent #event)
{
Body = contributor.GetBodyByID(#event.id);
}
}
}
using System;
using Alpaca.Systems;
namespace Alpaca.Systems.Kinect
{
public abstract class KinectComponent : AlpacaComponent
{
private KinectBody body;
public KinectBody Body
{
get
{
return body;
}
protected set
{
body = value;
}
}
}
}
using System.Collections.Generic;
using UnityEngine;
using Windows.Kinect;
using Alpaca.Utility;
namespace Alpaca.Systems.Kinect
{
public struct KinectBody
{
public Dictionary<JointType, KinectJoint> joints;
Dictionary<JointType, Windows.Kinect.Joint> rawJoints;
public bool isTracked;
public ulong trackingID;
public Vector3 position;
public Vector3 hipsDirection;
public Vector3 shouldersDirection;
public float bodyTurnAngle;
public Vector3 leftArmDirection;
public Vector3 rightArmDirection;
public void Init()
{
joints = new Dictionary<JointType, KinectJoint>(25, new JointTypeComparer());
}
public void RefineBody(Body body)
{
this.rawJoints = body.Joints;
for(int i = 0; i < 25; i++)
{
joints[KinectHelper.GetJointAtIndex(i)] = new KinectJoint(rawJoints[KinectHelper.GetJointAtIndex(i)]);
}
position = joints[JointType.SpineMid].position;
isTracked = body.IsTracked;
trackingID = body.TrackingId;
hipsDirection = Vector3.zero;
shouldersDirection = Vector3.zero;
bodyTurnAngle = 0;
leftArmDirection = Vector3.zero;
rightArmDirection = Vector3.zero;
}
public void ModifyJoint(JointType type, KinectJoint joint)
{
joints[type] = joint;
}
}
public class KinectBodyComparer : IEqualityComparer<KinectBody>
{
bool System.Collections.Generic.IEqualityComparer<KinectBody>.Equals(KinectBody x, KinectBody y)
{
return x.trackingID == y.trackingID;
}
int System.Collections.Generic.IEqualityComparer<KinectBody>.GetHashCode(KinectBody obj)
{
return unchecked((int) (obj.trackingID % 1000));
}
}
}
namespace Alpaca.Systems.Kinect
{
public abstract class BodyContributor
{
protected KinectBody[] bodies = new KinectBody[6];
private BodyRefiner refiner;
protected KinectBody emptyBody;
public BodyContributor(BodyRefiner refiner)
{
this.refiner = refiner;
emptyBody = new KinectBody();
}
public void Update()
{
this.bodies = refiner.GetBodies();
UpdateBodies();
}
protected abstract void UpdateBodies();
public KinectBody GetBodyByID(ulong id)
{
for(int i = 0; i < bodies.Length; i++)
{
KinectBody curBody = bodies[i];
if(curBody.trackingID == id)
{
return curBody;
}
}
return emptyBody;
}
public KinectBody[] GetBodies()
{
return bodies;
}
}
}

As Carsten has pointed out, KinectComponent is a class, a reference type.
KinectBody may be a value type, but it contains reference types (Dictionarys), which I suspect will lead to behaviour you don't expect.
Your struct also is large and mutable, which breaks these useful design guidelines

Related

C# Same methods for different argument type

I have this inteface:
public interface ICommand
{
bool Execute(Vector2 commandPosition);
bool Execute(GameUnit gameUnit);
bool Execute(string shortcut);
}
And a class with these methods making same things with different argument types
private void DispatchGameUnitCommand(GameUnit gameUnit)
{
if (_preparedCommand != null)
{
_preparedCommand.Execute(gameUnit);
return;
}
for (int i = 0; i < _commands.Length; i++)
{
if (_commands[i].Execute(gameUnit))
{
return;
}
}
}
private void DispatchLocationCommand(Vector2 screenPosition)
{
if (_preparedCommand != null)
{
_preparedCommand.Execute(screenPosition);
return;
}
for (int i = 0; i < _commands.Length; i++)
{
if (_commands[i].Execute(screenPosition))
{
return;
}
}
}
private void DispatchShortcutCommand(string shortcut)
{
if (_preparedCommand != null)
{
_preparedCommand.Execute(shortcut);
return;
}
for (int i = 0; i < _commands.Length; i++)
{
if (_commands[i].Execute(shortcut))
{
return;
}
}
}
How could I improve them removing duplicated code? Is it possible in anyways?
Your post says you have "a class with these methods" for GameUnit, Vector2 and string.
All indications in your code sample are that an actual GameUnit is required to do anything. In this case, the thing that "might" really help is having implicit conversion operators that turn a string or a Vector2 into a GameUnit.
GameUnit with implicit conversions
public class GameUnit
{
public Vector2 Vector2 { get; set; }
public string? Name { get; set; }
public static Dictionary<string, GameUnit> Shortcuts { get; }
= new Dictionary<string, GameUnit>();
public static implicit operator GameUnit(Vector2 vector)
{
return new GameUnit { Vector2 = vector };
}
public static implicit operator GameUnit(string shortcut)
{
Shortcuts.TryGetValue(shortcut, out GameUnit gameUnit);
return gameUnit; // Will be null if not in dict
}
public override string ToString() => $"{Vector2} {Name}";
}
Following this logic, we end up with a dispatcher class that needs only one method not three.
public class Dispatcher
{
public void DispatchGameUnitCommand(GameUnit context)
{
Console.WriteLine($"Dispatching {context}");
}
}
As for the interface, how were you planning on using it? So far, it's not needed for anything.
Testing
static void Main(string[] args)
{
Console.Title = "GameUnit Test";
Dispatcher exec = new Dispatcher();
GameUnit
adHoc = new GameUnit { Name = "AdHoc", Vector2 = new Vector2(5000, 2000) },
vectorA = new GameUnit { Name = "VectorA", Vector2 = new Vector2(5, 20) };
GameUnit.Shortcuts[adHoc.Name] = adHoc;
GameUnit.Shortcuts[vectorA.Name] = vectorA;
exec.DispatchGameUnitCommand(adHoc);
exec.DispatchGameUnitCommand("VectorA");
exec.DispatchGameUnitCommand(new Vector2(500, 200));
}

C# Roslyn TextSpan

Trying to analyze this code with Roslyn.
public class MyClass
{
#region FirstRegion
public void MyMethod()
{
}
#endregion
#region SecondRegion
public void MyMethod1()
{
}
private static void MyMethod3()
{
}
#endregion
}
At first I want to break it on regions and then to look what function is declared in each region.
var syntaxRoot = tree.GetRoot();
var regions = syntaxRoot.GetRegions();
foreach (var item in regions)
{
var publicFunctions = syntaxRoot.GetFunctions(item.FullSpan, Modificators.Public);
}
I thought that it can be done by specifying TextSpan
Region region = new Region();
region.Identifier = rawRegions[i].GetText().ToString();
region.FullSpan = new TextSpan(rawRegions[i].FullSpan.Start, rawRegions[i + 1].FullSpan.End - rawRegions[i].FullSpan.Start);
regions.Add(region);
But at the end i get that first regions contains two public methods, second region only one public method. It seems that in my case TextSpan is wrong, but why? How to fix this?
Program.cs
public class Modificators
{
public const string Public = "public";
public const string Private = "private";
public const string Protected = "protected";
}
public class Region
{
public string Identifier { get; set; }
public TextSpan FullSpan { get; set; }
}
public static class SyntaxExtensions
{
public static List<MethodDeclarationSyntax> GetFunctions(this SyntaxNode syntaxNode, TextSpan textSpan, string modifiers)
{
return syntaxNode.DescendantNodes(textSpan, null, false)
.OfType<MethodDeclarationSyntax>()
.Where(modificator => modificator.Modifiers.Any(x => x.Text.Contains(modifiers.ToString())))
.ToList();
}
public static List<Region> GetRegions(this SyntaxNode syntaxNode)
{
List<Region> regions = new List<Region>();
var rawRegions = syntaxNode.DescendantNodes(null, true).Where(x => x.RawKind == 8552 || x.RawKind == 8553).ToList();
for (int i = 0; i < rawRegions.Count; i = i + 2)
{
Region region = new Region();
region.Identifier = rawRegions[i].GetText().ToString();
region.FullSpan = new TextSpan(rawRegions[i].FullSpan.Start, rawRegions[i + 1].FullSpan.End - rawRegions[i].FullSpan.Start);
regions.Add(region);
}
return regions;
}
}
class Program
{
static void Main(string[] args)
{
var tree = CSharpSyntaxTree.ParseText(#"
public class MyClass
{
#region FirstRegion
public void MyMethod()
{
}
#endregion
#region SecondRegion
public void MyMethod1()
{
}
private static void MyMethod3()
{
}
#endregion
}");
var syntaxRoot = tree.GetRoot();
var regions = syntaxRoot.GetRegions();
foreach (var item in regions)
{
var publicFunctions = syntaxRoot.GetFunctions(item.FullSpan, Modificators.Public);
}
}
}

The Unit Test fails sometime due to bad design

Below are the two classes Sensor and Indicator which contains some business logic and a Unit Test. The unit test fails sometimes due to a bad design. I tried to fix the implementation and correct the unit test but I am still getting problem. I need your help to fix the implementation.
public class Sensor
{
const double Offset = 16;
public double GetFuelAmountValue()
{
double value;
SampleAmount(out value);
return Offset + value;
}
private static void SampleAmount(out double fuelTelemetryValue)
{
Random basicRandomNumbersGenerator = new Random();
fuelTelemetryValue = basicRandomNumbersGenerator.Next(0, 25);
}
}
public class Indicator
{
private const double LowFuelTreshold = 7;
private const double HighFuelTreshold = 21;
Sensor _sensor = new Sensor();
bool _alarm = false;
private long _alarmCount = 0;
public void Check()
{
double LitersOfFuelValue = _sensor.GetFuelAmountValue();
if (LitersOfFuelValue < LowFuelTreshold || HighFuelTreshold < LitersOfFuelValue)
{
_alarm = true;
_alarmCount += 1;
}
}
public bool Alarm
{
get { return _alarm; }
}
}
This is the test
[TestClass]
public class FuelIndicatorTest
{
[TestMethod]
public void Foo()
{
Indicator indicator = new Indicator();
indicator.Check();
Assert.AreEqual(false, indicator.Alarm);
}
}
I understand that this is a simplified code - not production one. Here one way how to mock random generated number FuelTelementryNumber and pass it in test via constructor.
public class Sensor
{
const double Offset = 16;
Func<double> _getFuelTelemetry;
public Sensor(Func<double> getFuelTelemetry)
{
_getFuelTelemetry = getFuelTelemetry;
}
public Sensor()
: this(SampleAmount)
{
}
public double GetFuelAmountValue()
{
double value = _getFuelTelemetry();
return Offset + value;
}
private static double SampleAmount()
{
Random basicRandomNumbersGenerator = new Random();
return basicRandomNumbersGenerator.Next(0, 25);
}
}
public class Indicator
{
private const double LowFuelTreshold = 7;
private const double HighFuelTreshold = 21;
Sensor _sensor;
public Indicator(Sensor sensor)
{
_sensor = sensor;
}
public Indicator() : this(new Sensor())
{
}
bool _alarm = false;
private long _alarmCount = 0;
public void Check()
{
double LitersOfFuelValue = _sensor.GetFuelAmountValue();
if (LitersOfFuelValue < LowFuelTreshold || HighFuelTreshold < LitersOfFuelValue)
{
_alarm = true;
_alarmCount += 1;
}
}
public bool Alarm
{
get { return _alarm; }
}
}
[TestClass]
public class FuelIndicatorTest
{
[TestMethod]
public void Foo()
{
Indicator indicator = new Indicator(new Sensor(() => {return 25;}));
indicator.Check();
Assert.AreEqual(true, indicator.Alarm);
}
}

c# using other class method

Thanks to NHMountainGoat for an answer!
Implementing Interface looks a good choice so we have only the 'needed' method instanciated.
It looks like this now:
EDIT
class Machine
{
//REM: MachineConnexion is a link to the main server where asking the data
internal linkToPLC LinkToPLC;
public IlinkToPLC ILinkPLC;
public interface IlinkToPLC//Interface to linkPLC
{
Int16 MachineNumIS { get; set; }
}
internal class linkToPLC : IlinkToPLC
{
private Int16 Act_MachineNum;
private List<string> genlnkPLCCanvas;
private List<string> genlnkPLCworkingwith;
static private List<string> ListSymbolNoExist;
private string[] ListToPLClnk = {
"GlobalFolder.PMachine[{0}].",
"GlobalFolder.PMachine[{0}].STATE.",
"GlobalFolder.Machine[{0}].",
"GlobalFolder.Machine[{0}].STATE.",
};
public linkToPLC()//ctor
{
genlnkPLCCanvas = new List<string>(ListToPLClnk);
genlnkPLCworkingwith = new List<string>(ListToPLClnk);
ListSymbolNoExist = new List<string>();
Act_MachineNum = MachineNumIS;
}
public Int16 MachineNumIS { get { return (Int16)ReadWriteMachine("data"); } set { ReadWriteMachine("data", value); } }
public string ValueExist(string ValueToreach, bool WorkingDATA = false)
{
if (!WorkingDATA)
{
for (int inc = 0; inc < genlnkPLCworkingwith.Count; inc++)
{
string StrValueToReach = genlnkPLCworkingwith[inc] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[inc] + ValueToreach);
}
}
else if (WorkingDATA)
{
string StrValueToReach = genlnkPLCworkingwith[10] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[10] + ValueToreach);
}
if (ListSymbolNoExist.Count != 0)
{
string ErrorList = "";
for (int inc = 0; inc < ListSymbolNoExist.Count; inc++)
{
ErrorList = string.Concat(ErrorList + "Num: " + inc.ToString() + " " + ListSymbolNoExist[inc].ToString() + "\n");
}
Console.WriteLine("Error" + ErrorList);
}
return null;
}
public object ReadWriteMachine(string VariableName, object DataToWrite = null, bool WorkingDATA = false)
{
string valueToFind = "";
if (ValueExist(VariableName) != "FALSE")
{
if (DataToWrite != null) { MachineConnexion.WriteSymbol(valueToFind, DataToWrite); }
return MachineConnexion.ReadSymbol(valueToFind);
}
return VariableName;
}
}
public Machine() //constructor
{
LinkToPLC = new linkToPLC();
}
}
And It doesn't work telling me that the reference object is not defined to an instance of the object..... in the line : Machine() LinkToPLC = new linkToPLC();//REM I found the bug, it was me ;o)) 24112016
//REM 24112016
What are the main differences between those two concept: static Instance and Interface?
Example:
class Program
{
static void Main(string[] args)
{
ITestInterface InterInstance = new TestInterface();
//test Interface
bool value1 = true;
value1 = InterInstance.invert(value1);
InterInstance.print(value1);
//test Instance static
TestStaticInstance staticInstance = new TestStaticInstance();
staticInstance.Instance.invert(value1);
staticInstance.Instance.print(value1);
Console.ReadKey();
}
}
class TestInterface : ITestInterface
{
public bool invert(bool value)
{
return !value;
}
public void print(bool value)
{
Console.WriteLine(value.ToString()+"\n");
}
private void methodX()
{ }
}
interface ITestInterface
{
bool invert(bool value);
void print(bool value);
}
public class TestStaticInstance
{
public TestStaticInstance Instance;
public TestStaticInstance()
{
Instance = this;
}
internal bool invert(bool value)
{
return !value;
}
internal void print(bool value)
{
Console.WriteLine(value.ToString());
}
}
Thanks
Can you structure your other classes to take an instance of the link class? See:
/// <summary>
/// just a stub to demonstrate the model
/// </summary>
internal class Machine
{
public string ReadData() { return "this is data"; }
public void WriteData(string data) { Console.WriteLine(data); }
}
internal interface IMachineDataAccessor
{
string Read();
void Write(string data);
}
class LinkClass : IMachineDataAccessor
{
protected Machine _machine;
public LinkClass(Machine machine)
{
_machine = machine;
}
public void DoMyWork()
{
// insert work somewhere in here.
string dataFromMachine = Read();
Write("outbound data");
}
public string Read()
{
return _machine.ReadData();
}
public void Write(string data)
{
_machine.WriteData(data);
}
}
class PersistentClass
{
IMachineDataAccessor _machineImpl;
public PersistentClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
class StateClass
{
IMachineDataAccessor _machineImpl;
public StateClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
static void Main(string[] args)
{
LinkClass link = new LinkClass(new Machine());
PersistentClass persistent = new PersistentClass(link as IMachineDataAccessor);
StateClass state = new StateClass(link as IMachineDataAccessor);
persistent.DoMyWork();
state.DoMyWork();
link.DoMyWork();
}

How to access array members that are of an interface type c#

I am a little lost here.
Basically, I need to access an array item, a string and display it. Here is the code.
namespace Test3_2_Practice
{
public partial class InterfaceImplementation : Form
{
//Array
ICombatant[] combatants = new ICombatant[2];
public InterfaceImplementation()
{
InitializeComponent();
}
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter ("Conan" , 500);
combatants[1] = new MonsterCharacter ("Bob" , 5);
combatants[2] = new MonsterCharacter ("Snake" , 15);
string output = "Fighters" + Environment.NewLine;
for (var i = 0; i < combatants.Length; i++)
{
var character = combatants[i];
output += "Character:" + combatants[i].
}
}
}
}
So I have my array, combatants composed of two types of instances. I want to access the name, "Conan" and add it to a string for output. How do I go about doing that? Here is the rest of the code if that helps. Thanks!
namespace Test3_2_Practice
{
//Interface
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
}
class PlayerCharacter : ICombatant
{
private string characterName;
private int currentHealth;
private int maxHealth;
public string CharacterName
{
get { return characterName; }
set { characterName = value; }
}
public int CurrentHealth
{
get { return currentHealth; }
set { currentHealth = value; }
}
public int MaxHealth
{
get { return maxHealth; }
set { maxHealth = value; }
}
public PlayerCharacter(string characterName, int maxHealth)
{
CharacterName = characterName;
CurrentHealth = MaxHealth = maxHealth;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if (damageAmount > currentHealth)
{
damageAmount = currentHealth;
return damageAmount;
}
else
{
currentHealth = currentHealth - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return ("Health " + CurrentHealth.ToString() + "/" + MaxHealth).ToString();
}
}
class MonsterCharacter : ICombatant
{
private string monsterName;
private int health;
public string MonsterName
{
get { return monsterName; }
set { monsterName = value; }
}
public int Health
{
get { return health; }
set { health = value; }
}
public MonsterCharacter(string monsterName, int health)
{
MonsterName = monsterName;
Health = health;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if(damageAmount > health)
{
damageAmount = health;
return damageAmount;
}
else
{
health = health - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return "Health " + Health;
}
}
}
Actually, since name is common to all implementer of interface that Name property should be included to interface itself like
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
public string CharacterName
{
get;
set;
}
}
In your current scenario, you will have to cast it specific concrete type before accessing it
var character = combatants[i];
if(character is PlayerCharacter)
output += "Character:" + ((PlayerCharacter)character).CharacterName;
It's better to make a good use of your interface. Create a new method in your interface:
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
string GetCombatantName(); // added this
}
Then implement in both classes which implements it:
class PlayerCharacter : ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Character: {0}", this.CharacterName);
}
}
class MonsterCharacter: ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Monster: {0}", this.MonsterName);
}
}
And use it like this:
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter("Conan", 500);
combatants[1] = new MonsterCharacter("Bob", 5);
combatants[2] = new MonsterCharacter("Snake", 15);
string output = "Fighters" + Environment.NewLine;
foreach (var combatant in combatants)
{
output += combatant.GetCombatantName();
}
}
So if one day you get ten distinct types of ICombatant (like AnimalCharacter, VirusCharacter), you don't have to nest a lot of ifs to check and cast types to get the proper property.
Interfaces are meant exactly to avoid this kind of stuff, hiding the implementation details.

Categories

Resources