|
It is, for objects - aka reference-types, not for value-types. C# is really strict on the difference.
The posted alternative with the interface does look like it (could) solve your problem. Alternatively, you could decide only to pass objects, and to wrap your ints in a MyInt class.
I are Troll
|
|
|
|
|
It's a design issue and it makes sense when you think about it. If you want to use a collection of type object, then use ArrayList. The generic List is a strongly typed version of ArrayList, so if strong typing is not required, use ArrayList.
"You get that on the big jobs."
|
|
|
|
|
Why not just to the following, from what I could see would give youthe exact same result, with the benefit of actually compiling!
public interface IBase<T>
{
Func<T> OnComplete { get; set; }
}
public class Base : IBase<object>
{
public Base(Func<object> onComplete)
{
OnComplete = onComplete;
}
public Func<object> OnComplete { get; set; }
}
public class GenericBase<T> : IBase<T>
{
public GenericBase(Func<T> onComplete)
{
OnComplete = onComplete;
}
public Func<T> OnComplete { get; set; }
}
|
|
|
|
|
Generic inheritance is a bit complicated. Here's the reason that you can't cast 'down' the generic type parameter inheritance tree.
Imagine this test class:
class BadMistake {
void CompleteHandler(Dictionary<string,int> complexParameter){
}
GenericBase<Dictionary<string,int>> instance;
public void CauseDeath(){
instance = new GenericBase<Dictionary<string,int>>(CompleteHandler);
((Base)instance).OnComplete(16);
}
}
Now, CompleteHandler is expecting to be passed a Dictionary, and you can't compile something which would cause that not to be the case. But using the base class, you can pass an int (or anything else) to it.
Method parameter compatibility for generics works backwards. This example will compile if the type parameter in the base is a subclass of T, for example try:
public class Base
{
public Func<T> OnComplete {get;set;} where T:Panel
public Base(Func<T> onComplete) where T:Panel
{
OnComplete = onComplete;
}
}
public class GenericBase<T> : Base
{
public GenericBase(Func<T> onComplete) where T:UserControl : base(onComplete)
{
OnComplete = onComplete;
}
}
(if I got the syntax on the constructor there right).
Also, there isn't really a reason to make a non generic base type and inherit from it in this way. You can just use a GenericBase<object> if you want one that can deal with anything.
|
|
|
|
|
Because it just can't. If asked questions such as this I like to mutter something about Covariance and Contravariance and wonder off. Usually works in the office environment anyway.
Regards,
Rob Philpott.
|
|
|
|
|
Rob Philpott wrote: Covariance and Contravariance
I thought those were added in .net 4.
|
|
|
|
|
|
Hi,
I'm growing grey early here... I severly need HELP.
When using Visual Studio 2010 (express?)...
...if you click File => "New Project", where do you specify the directory on disk?
I've been creating all sorts of project in random user directories and IT'S DRIVING ME CRAZY! Why can't I specify the directory where VS2010 creates the solution?!? Why can't I start a project in D:\projects?
This is one of the things which drives me away from .net, even tho it's the platform of choice here...
A good programmer is someone who always looks both ways before crossing a one-way street. (Doug Linder)
|
|
|
|
|
Helfdane wrote: I'm growing grey early here... I severly need HELP.
Really?
Visual Studio (all versions) behaves pretty much the same as most other Windows applications (e.g. MS Word): you can create a new something in memory, and it will ask you for a path if and when that becomes unavoidable, e.g. when telling the app to save, to close, to quit, to open up another thing that causes the current one to close first, etc. Then a dialog will pop up and you will be in charge of file locations.
I tend to save early on, to get that out of the way; but there is no need to do so.
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.
|
|
|
|
|
You're not correct regarding Visual Studio 2010 Express (10.0.30319.1 RTMel). There is only a project template (installer installed only the C# template) which you can choose and the only boxes where you can type something is the solution name and the search box.
A good programmer is someone who always looks both ways before crossing a one-way street. (Doug Linder)
|
|
|
|
|
I suggest you read my reply again. I did not say it was anywhere near the new-project dialog; I said the filepath is specified when you SAVE the project, not when you CREATE the project.
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.
|
|
|
|
|
I think I better go grab a coffee first before replying first thing this morning
A good programmer is someone who always looks both ways before crossing a one-way street. (Doug Linder)
|
|
|
|
|
Helfdane wrote: When using Visual Studio 2010 (express?)...
Check the about-box
Helfdane wrote: ..if you click File => "New Project", where do you specify the directory on disk?
Using the "location" textbox.
Helfdane wrote: Why can't I start a project in D:\projects?
Dunno, but you could ask your sysadmin. I can imagine how those user-specific folders are part of a regular backup-scheme. Visual Studio usually places your projects under the Documents-folder of your current user, in a subfolder with the name of the IDE, in a subfolder called "projects".
..but you should also be able to use the D:\projects location. You might even force it by moving the entire user-specific folders to the root of your D-drve, having the "My Documents" folder point there.
Helfdane wrote: This is one of the things which drives me away from .net, even tho it's the platform of choice here...
You could switch IDE[^] of course.
I are Troll
|
|
|
|
|
In the New Project window, click on the Browse button and navigate to the folder you wish to save your project.
"You get that on the big jobs."
|
|
|
|
|
You mean you want it to go to the same place all the time and create the solution directories there?
Menu: Tools|Options|Projects and Solutions|General - Projects Location
In VS2010 Ultimate, anyway.
|
|
|
|
|
GenJerDan wrote: In VS2010 Ultimate, anyway.
Express too.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
I wouldn't let CG touch my Abacus!
When you're wrestling a gorilla, you don't stop when you're tired, you stop when the gorilla is.
|
|
|
|
|
Thanx!
At first I missed the option "show all options". There it was when I enabled it.
A good programmer is someone who always looks both ways before crossing a one-way street. (Doug Linder)
|
|
|
|
|
Why does this event fire so often? I am using a binding source navigator for navigating a dataset, and it is giving me a world of grief. Whenever I click the next button I want to change the picture on the screen to reflect the new record. It looks like this:
DataRowView myRow = (DataRowView)this.dtObsDataBindingSource.Current;
try
{
this.pbPhoto.SizeMode = PictureBoxSizeMode.StretchImage;
this.pbPhoto.Image = Image.FromFile(myRow["txtPicPath"].ToString() + myRow["txtPhotoName"].ToString());
this.tbl_ref_categoryTableAdapter.Fill(this.ds_review.tbl_ref_category);
this.tbl_ref_defectTableAdapter.Fill(this.ds_review.tbl_ref_defect);
this.cboCategory.SelectedValue = myRow["intCategoryId"];
if (this.cboCategory.SelectedIndex != -1)
{
this.tbl_ref_defectTableAdapter.FillByCategoryId(this.ds_review.tbl_ref_defect, (int)this.cboCategory.SelectedValue);
}
this.cboDefect.SelectedValue = myRow["intDefectId"];
this.cboLocation.SelectedValue = myRow["intLocationId"];
}
catch (NullReferenceException)
{
this.pbPhoto.SizeMode = PictureBoxSizeMode.CenterImage;
this.pbPhoto.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath.ToString() + "\\noPic.jpg");
}
Long story short, the fact that this event fires three times causes me some grief, what is causing it to fire so many times? Is there a better event choice to handle this?
Cheers, --EA
|
|
|
|
|
Did you read the docs? Its *SUPPOSED* to get called a lot:
I know this isn't "CurrentItemChanged", but it says in the docs that "CurrentItemChanged" is equivalent to "CurrentChanged" and will get raised the same number of times:
The CurrentChanged event is raised whenever the Current property changes for any of the following reasons:
The current position of the List changes.
The DataSource or DataMember properties change.
The membership of the underlying List changes, which causes Position to refer to a different item. Examples include adding or deleting an item before the current item, deleting or moving the current item itself, or moving an item to the current position.
The underlying list is refreshed by a new sorting or filtering operation.
When this event is triggered, the Current property will already contain its new value.
CurrentChanged is the default event for the BindingSource class.
You simply need to filter out the conditions you don't care about. Or, if you don't have enough info to do that [EDIT: in the args I mean] (which is entirely possible), use a different event.
|
|
|
|
|
No I did not read the documentation, it frequently muddies the waters unnecessarily and fails to explain what I need to understand. In this instance you are right that the eventargs do not provide enough information to help, but I was able to go off of your idea and add the following:
if (myRow != (DataRowView)this.tbl_cdf_observationBindingSource.Current)
Which allows me to avoid processing everything if the datarow has not actually changed.
Cheers, --EA
|
|
|
|
|
Try using PositionChanged[^] instead, if all you require is to get the next/prev record.
The standard NavBar Next and Prev buttons just do Position +=(-=) 1;
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
I wouldn't let CG touch my Abacus!
When you're wrestling a gorilla, you don't stop when you're tired, you stop when the gorilla is.
|
|
|
|
|
Thank you, PositionChanged was a much better event for this particular situation than CurrentItemChanged. In my coding infancy I was looking for a method to change the picture when navigating a bindingsource and CurrentChanged was recommended. Now in my coding toddler days this is a better option. Thanks for the metaphorical programming potty training.
Cheers, --EA
|
|
|
|
|
I've been tasked with digging into an apparent memory leak in our project, and I have found something that sticks out to me (but wanting to hear opinions on this before I escalate this)
Architectural drive-by:
WCF Services, Repository Pattern. Repository references a service client and wraps around the call to the client Async methods.
public void GetAccount(int customerId, int accountId, Action<Entities.Account< onComplete>, Action<Exception> onError)
{
ServicesClient client = new ServicesClient();
client.GetAccountCompleted +=
(sender, response) =>
{
if(response.Error == null)
{
Entities.Account account = Mapper.Map<Account, Entities.Account>(resposne.Result.Account);
account.AccountState = Mapper.Map<AccountStatus, Entities.AccountState>(resposne.Result.AccountStatus);
account.AccountType = Mapper.Map<AccountType, Entities.AccountType>(resposne.Result.AccountType);
account.Location = Mapper.Map<Location, Entities.Location>(resposne.Result.Location);
account.Location.Address = Mapper.Map<Address, Entities.Address>(resposne.Result.Address);
this.GetAccountStateInfo(account,onComplete, onError);
}
else
{
onError.Invoke(response.Error);
}
};
client.GetAccountAsync(
new GetAccountRequest()
{
AccountId = accountId,
CustomerId = customerId,
SessionId = this.Logger.SessionId
});
}
ok...is there any reason why client.GetAccountCompleted would NOT need to be deregistered? (It is not. The block above contains a += but nowhere could I find a matching -=)
Thanks a lot for your time!
[edit to add:]
To clarify, ANTS Memory Profiler is reporting growth in unmanaged memory no matter what operation occurs and the Gen2 Heap seems to continually grow until an OOM Exception crashes the app.
We're using Telerik's Silverlight 4 controls, and it seems as if there *may* be some trouble coming from them (when I profile their online demo, I can repeat the memory growth pattern)
I have several leads on what the cause of this problem could be, but at this point I am uncertain whether this is "death by a thousand cuts" or a "decapitation." I probably should have realized that the above question I asked was not likely to be the root of the problem...the serviceClient does not implement IDisposable, but at this point my head is in "Plug the hole. Plug the hole. Plug the hole." mode.
btw....In the code snippet above, "Mapper" is the AutoMapper from Codeplex
"I need build Skynet. Plz send code"
modified on Thursday, March 31, 2011 9:51 AM
|
|
|
|
|
There could be, does client.GetAccountCompleted override the add method and keep a list of WeakReference's?
|
|
|
|
|
I don't see anything wrong here. client is a local variable, it dies when the GetAccount() method returns, what has been added/removed to its events is irrelevant for its own survival. In my experience, one seldom needs to deregister an event handler. Things would change however if there were some extra code that would store a reference to client, so it really depends on the "Map returned result to Client entity" part, which you didn't show.
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.
|
|
|
|