|
Hello experts,
how is it possible to create a class with a "tag" of any type that is still type-safe at runtime? That's what generics are for, I suppose.
Instances of that class need to have a reference to another instance of that class.
But then, the referenced instance should be allowed to host a tag of different type than the referencing instance.
I tried to build that in C#:
using System;
using System.Collections.Generic;
using System.Text;
namespace Test_Foo
{
public class Foo<T>
{
public T Tag;
public Foo<T> _innerFoo;
}
public class Bar
{
public void Baz()
{
Foo<int> intFoo = new Foo<int>();
intFoo.Tag = 5;
intFoo._innerFoo = new Foo<double>();
intFoo._innerFoo.Tag = 1.25D;
}
}
}
The marked declaration is where the linked class should go. What would possibly go between < and >?
The line marked as error-causing causes an error due to double not being implicitly convertible to int. This, I don't want to do anyway. I do want to have a double there.
How can the inner instance have a differently-typed tag than the outer one?
Ciao,
luker
|
|
|
|
|
Since your first instance of Foo<T> was made with an int the _innerFoo also is of type Foo<int>. The generic declaration of the class binds T for the whole scope of the class and thus also the definition of _innerFoo.
Cheers!
|
|
|
|
|
Interesting little problem. You can't do it the way you've written because once you declare what T is (an int), the same T is used throughout the entire class.
AFAICT, InnerFoo would have to be declared as a seperate class using it's own type place holder. Something like this:
public class Foo<T>
{
public T Tag;
public InnerFoo<S> _innerFoo;
public class InnerFoo<S>
{
public S Tag;
}
}
class Program
{
static void Main(string[] args)
{
Foo<int> intFoo = new Foo<int>();
intFoo.Tag = 5;
intFoo._innerFoo = new Foo<int>.InnerFoo<double>();
intFoo._innerFoo.Tag = 1.25D;
}
}
|
|
|
|
|
public class Foo<T>
{
public T Tag;
public class InnerFoo<S> : Foo<S>
{
}
public InnerFoo<S> _innerFoo;
}
Declaration of the InnerFoo class with its own tag type S seems to work.
But declaration of _innerFoo (marked line) fails due to S being not known yet. Declaring _innerFoo without a type parameter doesn't work either.
Is there another way to declare _innerFoo without knowing what type it is going to encapsulate?
Ciao,
luker
|
|
|
|
|
I tried that code on .NET 4.0 and it worked perfectly.
Since this method can only go one level deep, it's not going to work for you anyway.
Off the top of my head, the only other way I can find that would allow this removes all type checking on InnerFoo and introduces a performance penalty. That would be to declare InnerFoo As Object.
It appears as though you're putting together a chain of values of different types. You might want to look into a LinkedList to see if that helps.
|
|
|
|
|
Maybe it's a limitation of .NET 2.0, which I use. From what I read, it's the latest .NET version running on Windows 2000, which is mandatory for this project.
But the two-level limit should not be a problem for this design. Since InnerFoo<S> is derived from Foo<S>, it again should contain an inner foo class of different tag type.
Removing all type checking would equal my current design using object as tag type.
The linking is just one aspect of this class. LinkedList therefore doesn't serve its other needs.
However, I'm going to try the .NET 4.0 approach. Thanks for the hint.
Ciao,
luker
|
|
|
|
|
My bad - it doesn't work. I went back and replicated this and found that I did something wrong and it gave me the illusion that it worked!
I can't get this to work using Generics, but it does work like this:
namespace ClassLibrary1
{
public class Foo
{
public Type valueType;
public Object Tag;
public Foo innerFoo;
}
class Program
{
static void Main(string[] args)
{
Foo intFoo = new Foo();
intFoo.valueType = typeof(int);
intFoo.Tag = 5;
intFoo.innerFoo = new Foo();
intFoo.innerFoo.valueType = typeof(double);
intFoo.innerFoo.Tag = 1.25D;
}
}
}
Obviously, since Object is being used to store any type, there is a performance penalty to unbox the type and get the correct value.
|
|
|
|
|
Inherently you can't use generics like this. As you are aware, the class is strongly-typed, so _innerFoo is bound to the type of the class, so sorry but there is no way to do this.
|
|
|
|
|
Hi,
this seems to do what you want, somewhat:
namespace Test_Foo {
public class Foo<T, T2> {
public T Tag;
public Foo<T2, T2> _innerFoo;
}
public class Bar {
public void Baz() {
Foo<int, double> intFoo = new Foo<int, double>();
intFoo.Tag = 5;
intFoo._innerFoo = new Foo<double, double>();
intFoo._innerFoo.Tag = 1.25D;
}
}
}
However I don't know what purpose nesting those Foo's would serve as the inner Foo has its own inner Foo, etc.
My approach only works well for a nesting depth of 2, if your inner inner foo needs yet another type, you need to add another type parameter, etc.
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
Since the nesting depth is potentially limited only by available memory, and the sequence of tag types, if used this way, would have to be known at declaration time of the outermost foo, this approach seems not suitable yet.
For the purpose of nesting Foo's: It's an attempt to merge method return value and possible error handling without the performance impact of exception handling in case of an error.
And I personally don't like out-parameters too much.
Ciao,
luker
|
|
|
|
|
Even if technically possible, what's the logical need of accomplishing it?
Generics do allow specific types to be used, but this need is more like having a tree with each branch capable of bearing a different fruit
Code can solve a problem identified; but first identify the problem itself
|
|
|
|
|
As I said in the post you repied to, it's to combine result value and error handling.
The tree you mention is a good analogy to what I'm trying to create: there is a task to do with several sub-tasks which themselves have sub-sub-tasks. Each of those could fail and therefore return an error. Each could as well return some result just as expected.
The tree structure is built of error messages, including "There was no error. Everything went fine". Besides the error, especially in those "Everything fine" cases, there shall return a result value. It is of type object at the moment. I would like to have it type-safe. Therefore the need to tell the error object what type the nested return value should have.
Ciao,
luker
|
|
|
|
|
Hello,
I am writing simple server(publisher) and client(subscriber) application to imagine interprocess communication between two managed C# processes.
I need to write server(that's working as a publisher), it is publishing the contents to the subscriber on the basis of its subscriptions and client(subscriber). For this I have to write 2 seperate configuration files (app.config) on both publisher and subscriber's end. It's creating a problem. Publisher when want's to publish the data, it starts the process(client which's working as subscriber) with Process.Start statement. On start client process unable to initialize remoting, because it loads config.app which 's being used on server side. Where it did'nt find its own configurations(subscriber's configuration's).
I need to write both subscriber and publisher configuration on a single app.config file.How?
Regards,
Usman
|
|
|
|
|
The way I approached this was to create an assembly that managed access to a specific settings file, and referenced that assembly in all of the necessary applications. I posted an article that uses this technique here:
Synchronicity - A Folder Synchronizing Application[^]
The files you want to look at are:
AppSettingsBase.cs in the AppSettingsLib project
and
SyncSettings.cs in the SynchroLib project
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997
|
|
|
|
|
I digged out further and imagined that the problem i described, it will no longer be the issue at all. Can you please answer or help out the problem that I described. Because the problem now directed as this.
"How can Remoting Obj Uri be gernated at runtime at subscriber's end?"
|
|
|
|
|
Hello,
I have to work on one application that uses WCF web service. I know how to consume ASP.Net web service. May I know how consuming WCF web service different than ASP.Net service. Please, I want details for client only. Is it make any difference for proxy class.
Thanks in advance.
|
|
|
|
|
It is more or less similar if you are just calling the service operation without playing around with the requests or something else. Instead of adding web reference, add service reference. Or use svcutil to create the proxy class.
|
|
|
|
|
I have a function that loads data and configures the datagrid. I did this so that all the datagrids in the project would be the same. So I added a bit of code that is supposed to add row numbers to each of the datagrids.
<pre>
int numberofrows = DG.Rows.Count;
int len = numberofrows.ToString().Length;
string NumberForRow;
for (x = 0; x < DG.Rows.Count; x++)
{
NumberForRow = Convert.ToString(x + 1);
while (NumberForRow.Length < len)
{
NumberForRow = "0" + NumberForRow;
}
DG.Rows[x].HeaderCell.Value = NumberForRow;
}
</pre>
This code is fired as so
GF.LoadDataGrid(dgInvoices, DT, true,"InvoiceID,OrderID,Status,Date", "EVEN", "");
Where GF is GeneralFunctions class and LoadDataGrid is a method, the paramaters are dgInvoice is the DataGridView to load, DT is the DataTable, true/false is readonly, The first string is the Column headers, the second string is column spacing and the last string is columns that need to hidden if any. No the weird part. This line of code does not put in the Rowheader numbers. The DataGridView dgInvoices has an event tied to it that fills in another datagrid view with the detail of the invoice the call to fill that DataGridView is exactly the same
GF.LoadDataGrid(dgInvoiceDetail,DT,true,"ItemID,Description,Qty,Amount","EVEN","");
and for that datagrid the number do appear. I know that there is no difference between the two datagrids as on the form, I have copied and pasted the first datagrid to make the second datagrid so they are the same. Not sure what is going on.
Any help would be appreicated.
Thank you.
|
|
|
|
|
Member 2256533 wrote: int numberofrows = DG.Rows.Count;
int len = numberofrows.ToString().Length;
string NumberForRow;
for (x = 0; x < DG.Rows.Count; x++)
{
NumberForRow = Convert.ToString(x + 1);
while (NumberForRow.Length < len)
{
NumberForRow = "0" + NumberForRow;
}
DG.Rows[x].HeaderCell.Value = NumberForRow;
What length are you trying to get? this does not seem right. It looks you are trying to figure out how may digits are in a number. Is that right?
int len = numberofrows.ToString().Length;
int NumberForRow = 1;
foreach (DataGridViewRow row in DG.Rows)
{
if(NumberForRow < 10)
row.HeaderCell.Value = String.Format("{0:D2}", NumberForRow );
else
row.HeaderCell.Value = NumberForRow;
NumberForRow = NumberForRow+ 1;
}
|
|
|
|
|
True I am trying to find out how many digits are in the number so I can make the row headers all the same length. So if there are 1-9 rows the headers would look like 1,2,3,etc... and when there are 10-99 rows then 01,02...99, and 100-999 then 001,002,003...999 and this part works fine. The problem is that the row numbers don't show up at all in the first datagrid and they show up just fine in the second datagrid, using the exact same code.
|
|
|
|
|
For positive numbers this will do:
row.HeaderCell.Value = NumberForRow.ToString().PadLeft(requiredWidth, '0');
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
|
|
|
|
|
An update to the problem. I took the code above and made a separte function out of it. Then Added the call to it after the GF.LoadDataGrid call with the same result. No numbers. Then I added a button to the form that called the same function. After the page was rendered and I clicked said button and the numbers appeared. So it seems that for some reason after the numbers are put there and the grid is rendered the row numbers disappear. Not sure why?
|
|
|
|
|
Something like this won't do? (The DataGRidView has an unbound column added at column 0 for the index)
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow R in dataGridView1.Rows)
{
R.Cells[0].Value = R.Index;
}
}
EDIT: Oops. Never mind. Just noticed you want to put it in the row header cell....which doesn't work in the above code.
..and water fell from the sky like rain.
|
|
|
|
|
Daniel Soper appears to have a nice solution which he describes here
"You get that on the big jobs."
|
|
|
|
|
Hey ,
I have this task but I don't know what I should do , Please help me.
task :
-------------
An integer that is greater than zero is said to be n-factored if it has n distinct factors other than 1 and itself. For example 12 is 4-factored because its factors are 2, 3, 4, 6. A prime number is 0-factored.
Write a function named isNFactored that takes two arguments, an integer and some value of n, and returns 1 if the integer is n-factored. The function signature is
int isNFactored(int value, int n)
|
|
|
|