public class Vector
{
public int[] row = new int[2];
public Vector(int x, int y)
{
this.row[0] = x;
this.row[1] = y;
}
public int[] Row
{
get
{
return row;
}
}
}
public class Matrix<Vector>
{
public Vector[] rows = new Vector[2];
public Matrix(Vector v1, Vector v2){
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (Vector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
I'm getting 'Vector' does not contain a definition for 'row' and I have no idea why. It's set to public and I'm iterating over vector objects. What am I doing wrong here?
This is my first time using c#, coming from python so please don't mind the code if it doesn't make sense. Just toying with classes and syntax
here as you have written in your question,
public class Matrix<Vector>
means, your class Matrix is generic, and whatever type you will pass while creating an instance of Matrix, code of this class will take that type as Vector .
Note that your class Vector is total different type than the type Vector in Matrix class.
For ex.
if your create an object of matrix like this,
Matrix<string> m = new Matrix<string> ("amit", "maheshwari");
this will be valid and for this instacne of Matrix, Vector will be string. and yes string does not contain a definition for 'row' and so does Vecotr.
So, maybe you are misusing this class.
Or if you have created this class by your self and you want to perform what you have shown in question, there is no need to make this class generic.
public class Matrix
{
//so now this array of vector will be of class Vector
public Vector[] rows = new Vector[2];
public Matrix(Vector v1, Vector v2){
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (Vector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
public class Matrix<TVector> where TVector : Vector
{
public TVector[] rows = new TVector[2];
public Matrix(TVector v1, TVector v2)
{
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (TVector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
Thank you for John and other friends for reply quick answer. you must use TVector.
Related
how can I collect the name of all of my Script(Generic) (in a list or array?)
Like below?
public class inputdata
{
public Component com;
public int index;
public inputdata(Component newcom,int newindex)
{
com = newcom;
index = newindex;
}
}
inputdata[] data = {new inputdata(component1, 1),inputdata(component2, 1),inputdata(component3, 1)}
foreach (inputdata ft in data)
{
movefunc <ft.com> (ft.index);
}
void movefunc <T> (int index){
gameobject.GetComponent<T>()
}
it 's shows 'component1' is a type, which is not valid in the given context.
component1 is my c# script, I use it for detecting raycast.
like this
hitInfo.collider.gameObject.GetComponent <component1 > ()
It seems not clear what you are trying to achieve. In case it helps you can achive a list of the components in a gameObject like this:
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class GetComponets : MonoBehaviour {
public GameObject goWithComponets; //attach in the inspector
void Start() {
getComponets().ToList().ForEach(component => {
Debug.Log(component.GetType().ToString());
});
}
private IEnumerable<Component> getComponets() {
return goWithComponets.GetComponents<Component>().ToList(); ;
}
}
Your components wont be generic, they for sure will inherit from the Component type, so in case its needed you can grab all the components from the gameObject getting all the components from the base class Component, and if you need to handle specifics types, handle that later on with some code.
Sounds to me like you don't want a generic but rather something like e.g
public class inputdata
{
public Type Type;
public int Index;
public inputdata(Type type, int index)
{
Type = type;
Index = index;
}
}
inputdata[] data = new []
{
new inputdata(typeof(component1), 1),
new inputdata(typeof(component2), 1),
new inputdata(typeof(component3), 1)
};
and then
foreach (inputdata ft in data)
{
movefunc (ft.type, ft.index);
}
and
void movefunc (Type type, int index)
{
// ... whatever happens before and where you get the hitInfo from
if(hitInfo.collider.TryGetComponent(type, out var component))
{
// component of given type exists on the hit object
// "component" will contain a reference to it in the base type "Component" -> if you need it in its actual type you will need to cast
}
else
{
// there is no component of given type on the hit object
}
}
I have a very strange Behavior when merging two arrays together:
Assumptions
I have a class Tensor which contains an array float[] and a function AddTensorElements:
class Tensor
{
public float[] MovingAverage3h { get; set; }
public float[] MovingAverage6h { get; set; }
public float[] MovingAverage1d { get; set; }
public void AddTensorElements(Tensor input)
{
if (this.MovingAverage3h == null)
this.MovingAverage3h = input.MovingAverage3h;
this.MovingAverage6h = input.MovingAverage6h;
this.MovingAverage1d = input.MovingAverage1d;
}
else
{
this.MovingAverage3h = Concat(this.MovingAverage3h, input.MovingAverage6h);
this.MovingAverage6h = Concat(this.MovingAverage6h, input.MovingAverage6h);
this.MovingAverage1d = Concat(this.MovingAverage1d, input.MovingAverage1d);
}
private float[] Concat (float[] first, float[] second)
{
List<float> concatenated = new List<float>();
concatenated.AddRange(first);
concatenated.AddRange(second);
//foreach (float value in first) concatenated.Add(value);
//foreach (float value in second) concatenated.Add(value);
float[] returnArray = concatenated.ToArray();
return returnArray;
}
}
Within my main program, I repeatedly add the tensor M6t to the base tensor Minutes30[i]
class TensorCreator
{
private static List<Elements.Tensor> Minutes30 = new List<Elements.Tensor>();
private static void AddValues(Tensor M6t)
{
// Fill Minutes 30
Minutes30.Add(M6t);
for (int i = CounterM30; i < Minutes30.Count-1; i += M6)
{
{ } // Issue come up right here
Minutes30[i].AddTensorElements(M6t);
{ } // Issue come up right here
}
}
public static void AppendDataToTensor(Elements.Tensor queueElement)
{
// ...
AddValues(M6Avg);
}
}
Expected behavior vs actual behavior
The array within Minutes[i] expands
The array within M6t staysfloat[1]
So far so good, this works in a tiny separate test application
Within my actual application, the same code lets the baseTensor expand but also the input tensor gets expanded!
for (int i = CounterM30; i < Minutes30.Count-1; i += M6)
{
// M6T.Length == 1;
Minutes30[i].AddTensorElements(M6t);
// M6T.Length == Minutes30[i].Length;
}
strangely, whitin AddtensorToElements() I can see the values changing as well:
The Issue lies right here:
Minutes30.Add(M6t);
This adds a reference of Class Tensor M6t to Minutes 30. The result is that Minutes30[i] gets concatenated with it self.
Solution:
In class Tensor, add a Clone() method
public Tensor Clone()
{
Tensor tensor = new Tensor();
tensor.MovingAverage3h = this.MovingAverage3h.ToArray();
tensor.MovingAverage6h = this.MovingAverage6h.ToArray();
tensor.MovingAverage1d = this.MovingAverage1d.ToArray();
return tensor;
}
then change
Minutes30.Add(M6t);
to
Minutes30.Add(M6t.Clone());
EDIT: Updated to include actual code.
I am having an issue with some custom generic interfaces and I am not entirely sure what to do. The error I'm getting is:
Cannot convert from Map to IMap<ICell>
That error pops up when I try to pass Map as a parameter to a method that accepts IMap<ICell>. I have pasted sample code below. Just to be clear, FieldOfView doesn't use anything that hasn't been defined in ICell or IMap.
public class Map : IMap<Cell>
{
private FieldOfView _fieldOfView;
public int Width { get; }
public int Height { get; }
public Map(int width, int height)
{
Width = width;
Height = height;
_fieldOfView = new FieldOfView(this as IMap<ICell>);
_fieldOfView = new FieldOfView((IMap<ICell>)this);
}
public IEnumerable<Cell> GetAllCells()
{
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
yield return GetCell(x, y);
}
}
}
public Cell GetCell(int x, int y)
{
return new Cell(x, y);
}
public void Copy(IMap<Cell> sourceMap)
{
// ...
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var cell in GetAllCells())
{
sb.Append(cell.ToString());
}
return sb.ToString();
}
}
public interface IMap<T> where T : ICell
{
int Width { get; }
int Height { get; }
IEnumerable<T> GetAllCells();
T GetCell(int x, int y);
void Copy(IMap<T> sourceMap);
}
public class Cell : ICell
{
public int X { get; }
public int Y { get; }
public Cell(int x, int y)
{
X = x;
Y = Y;
}
public override string ToString()
{
return "overloaded";
}
}
public interface ICell
{
int X { get; }
int Y { get; }
}
public class FieldOfView
{
private readonly IMap<ICell> _map;
public FieldOfView(IMap<ICell> map)
{
_map = map;
}
public void DoStuff()
{
foreach (var cell in _map.GetAllCells())
{
// ...
}
}
}
This is similar to this stack overflow question, but a little different. I tried implementing an interface IMap as well as IMap<T> : IMap where T : ICell, but am having issues with that as well.
Lastly, I'm not sure if this is solvable with co/contravariance, but I am using C#3.0 so that is out of the picture for me (unless switching versions is the only way).
I think it would be fine with an implicit / direct cast?
_fieldOfView = new FieldOfView(this as IMap<ICell>); // or
_fieldOfView = new FieldOfView((IMap<ICell>)this);
But if there is a better way, I would like to do that. Resharper does throw me a warning when I cast Map to IMap<ICell> saying:
Suspicious cast: there is no type in the solution which is inherited from both Map and IMap<ICell>.
EDIT2: Look's like neither of the casts worked. I've decided instead to make Map be derived from IMap and just create the Cell objects where needed in the code.
Thanks #Rob and #MK87 for your help!
No, IMap<Cell> is not the same as IMap<ICell>, so this line:
_fieldOfView = new FieldOfView(this as IMap<ICell>);
will always pass null as parameter.
Yes, this is definitely solvable with variance.
For example, you can have:
IEnumerable<object> list = new List<string>();
since list is IEnumerable<outT>, that means that every IEnumerable<TT> with TT that derives from T is a valid value for list. So the List doesn't have to be of object, it can be of any derived type.
But because you can't use variance, we need another hack.
Possible solution: instead of deriving Map from IMap<Cell>, derive it from IMap<ICell>. You'll have only to correct some points, for example the return type of GetCell() must become ICell instead of Cell. Is it feasable for you?
I have a following problem:
I have interface ILocation, which includes functions to get position of feature (in 2D grid). Not all classes can have this interface, but those, which do, are not related to each other (do not inherit from each other etc.). I.e. classes with this interface are Person, Item, BuildingBlock...
Now I have class Location, which includes variable "block". Basically anything can be there, with one condition: it must implement interface ILocation. How can I do that? I do not know, which class will be in this variable, and therefore have to specify it as an Object, but I know, it must implement ILocation. How can this be done?
In following example, I want to implement method Symbol, which is in ILocation interface.
public class Location :ILocation
{
public int X {get; set;}
public int Y {get; set;}
public Object block;
public Location (int x, int y, Object o)
{
X = x;
Y = y;
block = o;
}
public char Symbol()
{
return block.Symbol();
}
}
And this of course produces an Error, since instance block of class Object does not implement ILocation.
So - how can I tell C#, that in variable "block" can be any object, which implements ILocation?
Thanks
Zbynek
Declare block variable as location:
public ILocation block;
public Location (int x, int y, ILocation o)
{
X = x;
Y = y;
block = o;
}
Either what lazyberezovsky said or, if you also need to keep knowledge of the exact type of block, you can use something with generics like:
public class Location<TBlock> : ILocation
where TBlock : ILocation
{
public int X { get; set; }
public int Y { get; set; }
public TBlock block;
public Location(int x, int y, TBlock o)
{
X = x;
Y = y;
block = o;
}
public char Symbol()
{
return block.Symbol();
}
}
Replace Object with ILocation.
public ILocation block;
public Location (int x, int y, ILocation o)
So whenever you make object of Location you can pass any object which implements ILocation interface.
var book = new Book(); // Book implements ILocation.
var person = new Person(); // Person implements ILocation.
var table = new Table(); // Table doesn't implement ILocation.
var bookLocation = new Location(1, 2, book);
var personLocation = new Location(2, 3, person);
var tableLocation = new Location(2, 3, table); // Compile error as table doesn't implement ILocation,
I want to create an Matrix class for some calculations. At my research i was stumble over some performance discussions Array[,] vs Array[][] and they conclusion was always use Array[][] if you want it fast
When i'm trying to provide access to an value via [][] it seems like i miss something important because i cant create an property like this
public double this[int iRow][int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
my problem is the second [] because the following works well
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
So what do i need to add in this class to let it work with [][] ?
public class Matrix
{
private bool _isSquare;
private double[][] matrix;
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
}
You can't do this in one class.
var b = a[1][2];
is the same as
var temp = a[1];
var b = temp[2];
They are two separate indexing operations.
Your first indexer would need to return an instance of some class that also has an indexer.
Using Indexers (C#)
Not sure what you are trying to do but if your matrix was the following you could still do what you are looking for
public class M
{
public double[][] Matrix { get; private set; }
public M()
{
Matrix = new double[2][]{new double[2], new double[2]};
}
}
M n = new M();
n.Matrix[0][0] = 1.0;