473,385 Members | 1,872 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

explicit cast between generic types

Jon
Hi,

When I try to compile the following generic class, the compiler gives
me many errors "Cannot conver type '...' to '...'" on the lines
indicated. Besides, the C# compiler gives me errors even if I don't
declare and instantiate C_Filter_MA<Ti,Tsin my program.
Ti and Ts should be one of {Byte, UInt16, UInt32, UInt64, SByte,
Int16, Int32, Int64, double}.

Any clue on how to be able to compile this class?
Thank you very much.

// ================================================== ============
public class C_Filter_MA<Ti,Ts>
{
// .................................................. ..........
protected Queue<Ti Ti_queue; // Queue (FIFO) that stores the
items.
protected Ts Ts_sum; // Sum of the values stored in the
queue.
...
// .................................................. ..........
...
// .................................................. ..........
public void Clear()
{
...
Ts_sum =(Ts)0; // <-- Compile error.
...
} // Clear
// .................................................. ..........
public Ti InOutData(Ti Ti_in)
{
...
Ts_sum -=(Ts)Ti_queue.Dequeue(); // <-- Compile error.
...
Ts_sum +=(Ts)Ti_in; // <-- Compile error.
...
} // InOutData
// .................................................. ..........
} // C_Filter_MA
// ================================================== ============

Dec 10 '07 #1
6 2698
Jon,

Why do you have two types to begin with? How is it that the sum of
types Ti equals a ^NEW^ type Ts? Why wouldn't you just need one type, Ti?

As for the Clear method, you can fix this by using default:

public void Clear()
{
// This should probably be Ti, the same could be applied.
Ts_sum = default(Ti);
} // Clear

If Ti is a blittable type, then an instance of that type will be created
with the data set to 0 for all bits in the type. In the case of int,
double, etc, etc, that means values of 0.

Changing to Ti will fix the Dequeue issue as well.

As for adding, you aren't going to be able to do much with that, since
the constraint system doesn't tell the compiler anything about operations on
a type. Because of this, you will need another class that handles this.
First, you have to define an interface like this:

interface ISimpleMath<T>
{
T Add(T value1, T value2);
T Subtract(T value1, T value2);
}

Then, you implement it for each of the types you want to use, like so:

class IntSimpleMath: ISimpleMath<int>
{
public int Add(int value1, int value2)
{
// Return the sum.
return value1 + value2;
}

public int Subtract(int value1, int value2)
{
// Return the difference.
return value1 - value2;
}
}

Finally, you would add a second type to your generic type which would
indicate the type used to perform the adding:

public class C_Filter_MA<Ti, TSimpleMathwhere TSimpleMath:
ISimpleMath<Ti>, new()
{
// Assuming that the operations on the implementation of ISimpleMath are
thread-safe (and
// they should be, since you are passing all operands into the method
and not storing
// shared state), you can store one instance and use that across all
instances of the type.
private static readonly SimpleMathImplementation = new TSimpleMath();

// .................................................. ..........
protected Queue<Ti Ti_queue; // Queue (FIFO) that stores the items.

// Changed to be of type Ti.
protected Ti Ts_sum; // Sum of the values stored in the queue.

public void Clear()
{
Ts_sum = default(Ti)
} // Clear

public Ti InOutData(Ti Ti_in)
{
// Get the item.
Ti item = Ti_queue.Dequeue();

// Subtract from the sum.
Ts_sum = SimpleMathImplementation.Subtract(Ts_sum, item);

// Add the item passed in.
Ts_sum = SimpleMathImplementation.Add(Ts_sum, Ti_in);
} // InOutData
} // C_Filter_MA
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Jon" <jm*@hotmail.comwrote in message
news:mp********************************@4ax.com...
Hi,

When I try to compile the following generic class, the compiler gives
me many errors "Cannot conver type '...' to '...'" on the lines
indicated. Besides, the C# compiler gives me errors even if I don't
declare and instantiate C_Filter_MA<Ti,Tsin my program.
Ti and Ts should be one of {Byte, UInt16, UInt32, UInt64, SByte,
Int16, Int32, Int64, double}.

Any clue on how to be able to compile this class?
Thank you very much.

// ================================================== ============
public class C_Filter_MA<Ti,Ts>
{
// .................................................. ..........
protected Queue<Ti Ti_queue; // Queue (FIFO) that stores the
items.
protected Ts Ts_sum; // Sum of the values stored in the
queue.
...
// .................................................. ..........
...
// .................................................. ..........
public void Clear()
{
...
Ts_sum =(Ts)0; // <-- Compile error.
...
} // Clear
// .................................................. ..........
public Ti InOutData(Ti Ti_in)
{
...
Ts_sum -=(Ts)Ti_queue.Dequeue(); // <-- Compile error.
...
Ts_sum +=(Ts)Ti_in; // <-- Compile error.
...
} // InOutData
// .................................................. ..........
} // C_Filter_MA
// ================================================== ============

Dec 10 '07 #2
Ts_sum -=(Ts)Ti_queue.Dequeue(); // <-- Compile error.
Ts_sum +=(Ts)Ti_in; // <-- Compile error.

For info, I have a working generic math implementation as an in-
progress side project. It includes standard operators and conversion;
it runtime (not compile-time) validated but is very fast.

I posted some of it on this forum previously, but let me know if this
is of interest.

Marc
Dec 10 '07 #3
Jon
Hi Nicholas,

I tried your custom interface solution. I end up with only 4 compile
erros, in two lines. Search for token "errors" in the source code
shown below. In line

private static readonly Ts_SimpleMathImplementation= new
Ts_SimpleMath();

it is like it doesn't know how to create a new instance of
Ts_SimpleMath. The "new ()" in line

where Ti_SimpleMath : I_SimpleMath<Ti>, new()

presumably means that Ti_SimpleMath must have a public parameterless
constructor. How can I specify the constructor of Ti_SimpleMath ? In
I_SimpleMath<T>? How?

I know that I ended up not using "Ti_SimpleMathImplementation", but I
would keep it just in case. I do use "Ts_SimpleMathImplementation".

Sorry about the long post.

If you know why I'm getting those errors, please let me know.
Thank you.

PS: I'm starting to think about not using generics for this purpose,
and instead define two or three classes like "C_Filter_MA_u08_u32",
"C_Filter_MA_u16_u32" and "C_Filter_MA_double_double", for instance,
because I'll probably end up with fewer lines of code. All this has
really surprised me.
---------------------------------------
using System;
using System.Collections.Generic;

// These "using" are the C# equivalent ones to "typedef" in C++.
using u08 =System.Byte;
using u16 =System.UInt16;
using u32 =System.UInt32;
using u64 =System.UInt64;

using i08 =System.SByte;
using i16 =System.Int16;
using i32 =System.Int32;
using i64 =System.Int64;

namespace N_Filters
{
#region Interfaces and their implementations.
// ================================================== =============
// Interfaces cannot contain operators.
public interface I_SimpleMath<T>
{
T Add(T val1, T val2);
T Subtract(T val1, T val2);
T Multiply(T val1, T val2);
T Divide(T val1, T val2);
T ShiftLeft(T val1,u08 shift_amount);
T ShiftRight(T val1,u08 shift_amount);
} // I_SimpleMath
// ================================================== =============
public class C_SimpleMath_u08 : I_SimpleMath<u08>
{
public u08 Add(u08 val1, u08 val2)
{
return((u08)(val1+val2));
}
public u08 Subtract(u08 val1, u08 val2)
{
return((u08)(val1-val2));
}
public u08 Multiply(u08 val1, u08 val2)
{
return((u08)(val1*val2));
}
public u08 Divide(u08 val1, u08 val2)
{
return((u08)(val1/val2));
}
public u08 ShiftLeft(u08 val1,u08 shift_amount)
{
return((u08)(val1<<shift_amount));
}
public u08 ShiftRight(u08 val1,u08 shift_amount)
{
return((u08)(val1>>shift_amount));
}
} // C_SimpleMath_u08
// ================================================== =============
public class C_SimpleMath_u16 : I_SimpleMath<u16>
{
public u16 Add(u16 val1, u16 val2)
{
return((u16)(val1+val2));
}
public u16 Subtract(u16 val1, u16 val2)
{
return((u16)(val1-val2));
}
public u16 Multiply(u16 val1, u16 val2)
{
return((u16)(val1*val2));
}
public u16 Divide(u16 val1, u16 val2)
{
return((u16)(val1/val2));
}
public u16 ShiftLeft(u16 val1,u08 shift_amount)
{
return((u16)(val1<<shift_amount));
}
public u16 ShiftRight(u16 val1,u08 shift_amount)
{
return((u16)(val1>>shift_amount));
}
} // C_SimpleMath_u16
// ================================================== =============
public class C_SimpleMath_u32 : I_SimpleMath<u32>
{
public u32 Add(u32 val1, u32 val2)
{
return((u32)(val1+val2));
}
public u32 Subtract(u32 val1, u32 val2)
{
return((u32)(val1-val2));
}
public u32 Multiply(u32 val1, u32 val2)
{
return((u32)(val1*val2));
}
public u32 Divide(u32 val1, u32 val2)
{
return((u32)(val1/val2));
}
public u32 ShiftLeft(u32 val1,u08 shift_amount)
{
return((u32)(val1<<shift_amount));
}
public u32 ShiftRight(u32 val1,u08 shift_amount)
{
return((u32)(val1>>shift_amount));
}
} // C_SimpleMath_u32
// ================================================== =============
public class C_SimpleMath_u64 : I_SimpleMath<u64>
{
public u64 Add(u64 val1, u64 val2)
{
return((u64)(val1+val2));
}
public u64 Subtract(u64 val1, u64 val2)
{
return((u64)(val1-val2));
}
public u64 Multiply(u64 val1, u64 val2)
{
return((u64)(val1*val2));
}
public u64 Divide(u64 val1, u64 val2)
{
return((u64)(val1/val2));
}
public u64 ShiftLeft(u64 val1,u08 shift_amount)
{
return((u64)(val1<<shift_amount));
}
public u64 ShiftRight(u64 val1,u08 shift_amount)
{
return((u64)(val1>>shift_amount));
}
} // C_SimpleMath_u64
// ================================================== =============
public class C_SimpleMath_i08 : I_SimpleMath<i08>
{
public i08 Add(i08 val1, i08 val2)
{
return((i08)(val1+val2));
}
public i08 Subtract(i08 val1, i08 val2)
{
return((i08)(val1-val2));
}
public i08 Multiply(i08 val1, i08 val2)
{
return((i08)(val1*val2));
}
public i08 Divide(i08 val1, i08 val2)
{
return((i08)(val1/val2));
}
public i08 ShiftLeft(i08 val1,u08 shift_amount)
{
return((i08)(val1<<shift_amount));
}
public i08 ShiftRight(i08 val1,u08 shift_amount)
{
return((i08)(val1>>shift_amount));
}
} // C_SimpleMath_i08
// ================================================== =============
public class C_SimpleMath_i16 : I_SimpleMath<i16>
{
public i16 Add(i16 val1, i16 val2)
{
return((i16)(val1+val2));
}
public i16 Subtract(i16 val1, i16 val2)
{
return((i16)(val1-val2));
}
public i16 Multiply(i16 val1, i16 val2)
{
return((i16)(val1*val2));
}
public i16 Divide(i16 val1, i16 val2)
{
return((i16)(val1/val2));
}
public i16 ShiftLeft(i16 val1,u08 shift_amount)
{
return((i16)(val1<<shift_amount));
}
public i16 ShiftRight(i16 val1,u08 shift_amount)
{
return((i16)(val1>>shift_amount));
}
} // C_SimpleMath_i16
// ================================================== =============
public class C_SimpleMath_i32 : I_SimpleMath<i32>
{
public i32 Add(i32 val1, i32 val2)
{
return((i32)(val1+val2));
}
public i32 Subtract(i32 val1, i32 val2)
{
return((i32)(val1-val2));
}
public i32 Multiply(i32 val1, i32 val2)
{
return((i32)(val1*val2));
}
public i32 Divide(i32 val1, i32 val2)
{
return((i32)(val1/val2));
}
public i32 ShiftLeft(i32 val1,u08 shift_amount)
{
return((i32)(val1<<shift_amount));
}
public i32 ShiftRight(i32 val1,u08 shift_amount)
{
return((i32)(val1>>shift_amount));
}
} // C_SimpleMath_i32
// ================================================== =============
public class C_SimpleMath_i64 : I_SimpleMath<i64>
{
public i64 Add(i64 val1, i64 val2)
{
return((i64)(val1+val2));
}
public i64 Subtract(i64 val1, i64 val2)
{
return((i64)(val1-val2));
}
public i64 Multiply(i64 val1, i64 val2)
{
return((i64)(val1*val2));
}
public i64 Divide(i64 val1, i64 val2)
{
return((i64)(val1/val2));
}
public i64 ShiftLeft(i64 val1,u08 shift_amount)
{
return((i64)(val1<<shift_amount));
}
public i64 ShiftRight(i64 val1,u08 shift_amount)
{
return((i64)(val1>>shift_amount));
}
} // C_SimpleMath_i64
// ================================================== =============
public class C_SimpleMath_double : I_SimpleMath<double>
{
public double Add(double val1, double val2)
{
return((double)(val1+val2));
}
public double Subtract(double val1, double val2)
{
return((double)(val1-val2));
}
public double Multiply(double val1, double val2)
{
return((double)(val1*val2));
}
public double Divide(double val1, double val2)
{
return((double)(val1/val2));
}
public double ShiftLeft(double val1,u08 shift_amount)
{
return(val1*Math.Pow(2.0,(double)shift_amount));
}
public double ShiftRight(double val1,u08 shift_amount)
{
return(val1*Math.Pow(2.0,(double)shift_amount*-1.0));
}
} // C_SimpleMath_double
#endregion
// ================================================== =============
// Moving average filter.
// Ti = T_item {u08,u16,u32,u64,i08,i16,i32,i64,double}.
// Ts = T_sum {u08,u16,u32,u64,i08,i16,i32,i64,double}.

public class C_Filter_MA<Ti,Ti_SimpleMath,Ts,Ts_SimpleMath>
where Ti : IComparable, IFormattable, IConvertible,
IComparable<Ti>, IEquatable<Ti>
where Ti_SimpleMath : I_SimpleMath<Ti>, new()
where Ts : IComparable, IFormattable, IConvertible,
IComparable<Ts>, IEquatable<Ts>
where Ts_SimpleMath : I_SimpleMath<Ts>, new()
{
// .................................................. ...........
private static readonly Ti_SimpleMathImplementation= new
Ti_SimpleMath(); // <-- Compile errors "Invalid token '=' in class,
struct, or interface member declaration" and "Class, struct, or
interface method must have a return type".
private static readonly Ts_SimpleMathImplementation= new
Ts_SimpleMath(); // <-- Compile errors "Invalid token '=' in class,
struct, or interface member declaration" and "Class, struct, or
interface method must have a return type".
// .................................................. ...........
protected Queue<Ti Ti_queue; // Queue (FIFO) that
stores the items.
public int Ti_queue_capacity; // Queue does not
have any member field called Capacity.
protected Ts Ts_sum; // Sum of the values
stored in the queue.
protected u08 u08_log2ofsize; // Log2(<size of
fifo>). So, size of fifo will always be a power of 2.
// .................................................. ...........
public C_Filter_MA(u08 u08_log2ofsize)
{
this.u08_log2ofsize=u08_log2ofsize;
Ti_queue_capacity=1<<u08_log2ofsize;
Ti_queue=new Queue<Ti>(Ti_queue_capacity);
Clear();
} // C_Filter_MA
// .................................................. ...........
public void Clear()
{
Ti_queue.Clear();
Ts_sum=default(Ts);
} // Clear
// .................................................. ...........
public void Init(Ti Ti_initial)
{
Ti_queue.Clear();

Ts_sum=(Ts)Convert.ChangeType(Ti_initial.ToInt32() *Ti_queue_capacity,typeof(Ts));
if (Ti_initial.Equals(default(Ti))) return;
for (int i=0;i<Ti_queue_capacity;i++)
{
Ti_queue.Enqueue(Ti_initial);
} // for
} // Init
// .................................................. ...........
public Ti InOutData(Ti Ti_in)
{
if (Ti_queue.Count>=Ti_queue_capacity)
{

Ts_sum=Ts_SimpleMathImplementation.Subtract(Ts_sum ,(Ts)Convert.ChangeType(Ti_queue.Dequeue(),typeof( Ts)));
} // if
Ti_queue.Enqueue(Ti_in);

Ts_sum=Ts_SimpleMathImplementation.Add(Ts_sum,(Ts) Convert.ChangeType(Ti_in,typeof(Ts)));
return(
(Ti)Convert.ChangeType(Ts_SimpleMathImplementation .ShiftRight(Ts_sum,u08_log2ofsize),typeof(Ti))
);
} // InOutData
// .................................................. ...........
} // C_Filter_MA
// ================================================== =============
} // N_Filters

Dec 11 '07 #4
Jon
On Mon, 10 Dec 2007 14:27:33 -0800 (PST), Marc Gravell
<ma**********@gmail.comwrote:
Ts_sum -=(Ts)Ti_queue.Dequeue(); // <-- Compile error.
Ts_sum +=(Ts)Ti_in; // <-- Compile error.

For info, I have a working generic math implementation as an in-
progress side project. It includes standard operators and conversion;
it runtime (not compile-time) validated but is very fast.

I posted some of it on this forum previously, but let me know if this
is of interest.

Marc
Even though I prefer compile-time validation, I would be glad to take
a look at your implementation. If you have a link, please let me know.
Otherwise, please write me at "cucafera (at) telefonica (dot) com"

Thank you.

Dec 11 '07 #5
I have e-mailed you a sample, but I've also just noticed that you
mention CF. Unfortunately, the code doesn't compile in CF 3.5, as it
uses some framework classes that aren't supported on that platform. It
may be possible to re-work the concept using Delegate.CreateDelegate
and the various operators, but there are a lot of special cases where
the operator is supplied by the compiler (not the Type) which would
need surrogate methods (which is partly what I was hoping to avoid).

Marc
Dec 11 '07 #6
but that didn't work either. It still doesn't know how to add or
subtract. My quesion is: Isn't there any existing interface, which
would be common to the integral and floating point types, which
exposes methods so common as adding, subtracting, multiplying, etc?
You've just nailed the biggest complaint about generics.
Dec 31 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Stub | last post by:
Docs says that "The compiler does not use an explicit constructor to implement an implied conversion of types. It's purpose is reserved explicitly for construction." I put up code of three cases...
3
by: /* frank */ | last post by:
Explicit conversion is made by mean of a cast i.e. float a; int b; .... b = (int) a; But the implicit conversion? What is?
2
by: babylon | last post by:
I have an enum public enum MyEnum : int { X, Y } I have to do int a = (int) MyEnum.X; can i overload the operator or other means to do something like
31
by: Michael C | last post by:
If a class inherits from another class, say Form inherits from control, then I can assign the Form to a variable of type Control without needing an explicit conversion, eg Form1 f = new Form1();...
2
by: COLIN JACK | last post by:
Hi All, I've got a situation where I'm implementing an interface (BaseInterface in example below) and I want to use explicity interface implementation of an event so that I can add type safety. ...
10
by: Chet Cromer | last post by:
I am creating a set of base classes and sub classes to use throughout a program I'm developing. The base class represents a generic "lookup table" from my database that contains lists of things...
14
by: Noone | last post by:
Hello all, Ok, I want to create a program that will load plugins (dll's) from a plugin folder. I can create the forms and put them into a dll but I cannot actually add them dynamically at run...
8
by: Skysurfer | last post by:
Hi. I have some control of different type which have a particolar property, for instance MyProp. Some other controls don't have this property. How can i make a generic sub that set this property...
15
by: Lloyd Dupont | last post by:
Don't mistake generic type for what you would like them to be!! IFoo<Ahas nothing in common with IFoo<B>! They are completely different type create dynamically at runtime. What you ask is a...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.