Cannot convert from class to generic interface - c#

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?

Related

Can't access class field in another class

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.

C#: Interface instead of class in variable definition

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,

How to make a arrayclass access with this[][]

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;

Is this how we create a structural object hierarchy (object model) like Excel VBA?

I want to learn how to create an object hierarchy (like that of excel vba).
I have written some code and want to ask if this is the right way to go. Also, I want to know if creating this type of object structure will have any significant effect on performance. I will access the objects as for e.g. this way :
Hotel hotel = new Hotel();
int x = hotel.Rooms[1].Count; // just an example
int y = hotel.Rooms.Room.Count; // just an example
class Hotel
{
private int i;
public Hotel()
{
i = 10; // some prossessing to give the value of i. Lets say 10
}
public _Rooms Rooms
{
get { return new _Rooms(i); }
}
}
class _Rooms
{
private int _i;
public _Rooms(int i)
{
this._i = i;
}
public _Room this[int i]
{
get { return new _Room(_i); }
}
public _Room Room // _Room Property
{
get { return new _Room(this._i); }
}
}
class _Room
{
private int _i;
public _Room(int i)
{
// some prossessing to give the value of i. Lets say :
_i = i + 10;
}
public int Count
{
get { _i = 15; return _i; }
}
}
This is just a simple example of the model that I want to achieve.

More efficent ways of cleanly dealing with a multi-dimensional array keyd by enums

I have a situation where I need to do many gets/sets, after perfomance analysis this is one of the more expensive parts of my application. Origionally I was using a Dictionary but switched to a jagged array internally which gave it a signficant perfomance boost, still I'd like to see if theres a way to improve the perfomance of this code without ditching the nice and useable syntax.
Note calling Convert.ToInt32 is signficantly more expensive than calling a cast, and since the generic constraint TStatus : int doesn't work for an enum I had to implement this as a abstract class, it would be nice if this collection would work with any enum out of the box.
Also I tried implementing yield for the IEnumerable, however that was actually slower than just populating a list.
public abstract class LoanStatusVectorOverTime<TStatus> : ILoanStatusVectorOverTime<TStatus>
where TStatus: struct
{
protected static readonly TStatus[] LoanStatusTypes = (TStatus[])Enum.GetValues(typeof(TStatus));
protected static readonly int LoanStatusCount = Enum.GetValues(typeof(TStatus)).Length;
protected const int MonthsSinceEventCount = 25;
private readonly object SYNC = new object();
protected double[,] VectorDictionary { get; set; }
public LoanStatusVectorOverTime()
{
this.VectorDictionary = new double[LoanStatusCount, MonthsSinceEventCount];
}
public double this[TStatus status, int monthsSince]
{
get
{
if (monthsSince >= MonthsSinceEventCount)
return 0;
return VectorDictionary[GetKeyValue(status), monthsSince];
}
set
{
if (monthsSince >= MonthsSinceEventCount)
return;
VectorDictionary[GetKeyValue(status), monthsSince] = value;
}
}
public double SumOverStatus(TStatus status)
{
double sum = 0;
foreach (var fromStatus in LoanStatusTypes)
{
int i = 0;
while (i < MonthsSinceEventCount)
{
sum += VectorDictionary[GetKeyValue(fromStatus), i];
i++;
}
}
return sum;
}
public IEnumerator<KeyValuePair<Tuple<TStatus, int>, double>> GetEnumerator()
{
List<KeyValuePair<Tuple<TStatus, int>, double>> data = new List<KeyValuePair<Tuple<TStatus, int>, double>>();
foreach (var fromStatus in LoanStatusTypes)
{
int i = 0;
while (i < MonthsSinceEventCount)
{
var val = VectorDictionary[GetKeyValue(fromStatus), i];
if (val != default(double))
data.Add(new KeyValuePair<Tuple<TStatus, int>, double>(new Tuple<TStatus, int>(fromStatus, i), val));
i++;
}
}
return data.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
protected abstract int GetKeyValue(TStatus status);
protected abstract ILoanStatusVectorOverTime<TStatus> Initalize();
public ILoanStatusVectorOverTime<TStatus> Copy()
{
var vect = Initalize();
foreach (var fromStatus in LoanStatusTypes)
{
int i = 0;
while (i < MonthsSinceEventCount)
{
vect[fromStatus, i] = VectorDictionary[GetKeyValue(fromStatus), i];
i++;
}
}
return vect;
}
public double SumOverAll(int monthsSince = 1)
{
double sum = 0;
foreach (var status in LoanStatusTypes)
{
sum += this[status, monthsSince];
}
return sum;
}
}
public class AssetResolutionVector : LoanStatusVectorOverTime<AssetResolutionStatus>
{
protected override int GetKeyValue(AssetResolutionStatus status)
{
return (int)status;
}
protected override ILoanStatusVectorOverTime<AssetResolutionStatus> Initalize()
{
return new AssetResolutionVector();
}
}
var arvector = new AssetResolutionVector();
arvector[AssetResolutionStatus.ShortSale, 1] = 10;
If the enum to int conversion is taking up a lot of your time, make sure that don't do the conversion during every iteration of your inner loop. Here's an example of the conversion getting cached for your SumOverStatus method:
public double SumOverStatus(TStatus status)
{
double sum = 0;
foreach (var fromStatus in LoanStatusTypes)
{
int statusKey = GetKeyValue(fromStatus);
int i = 0;
while (i < MonthsSinceEventCount)
{
sum += VectorDictionary[statusKey, i];
i++;
}
}
return sum;
}
Extra tip: although it may not have give a performance boost, you can avoid making your class abstract by using a Func<TStatus, int> converter. Here's how the converter could be exposed as a property (a constructor argument would work fine too):
public class LoanStatusVectorOverTime<TStatus>
{
public Func<TStatus, int> GetKeyValue { get; set; }
}
// When the object gets instantiated
loanStatusVectorOverTime.GetKeyValue = status => (int)status;
It sounds like you have two separate problems here:
Converting from an enum to an integer has an overhead when the conversion is being done using an abstract method or a delegate. You have two options here:
A. Take out the generic parameter from your class and hardcode the enum type (making multiple copies of the class if necessary).
B. Have your accessors take two integers instead of an enum and an integer (letting the client do a cheap cast from enum to integer).
A lot of time is being used during get/set. This may not be because get/set are inefficient, but because get/set are being called too many times. Suggestions:
A. Group your operations by month or by status, restructure your data structures (maybe using nested arrays), and write efficient loops.
B. Reduce the computational complexity of the code that is doing all the getting and setting. By stepping back and mapping out your program, you may find more efficient algorithms.

Categories

Resources