How do I use if/else in a generic function? C#
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the <
operand.
public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Any idea on how to tackle this problem?
c#
|
show 8 more comments
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the <
operand.
public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Any idea on how to tackle this problem?
c#
2
This is a common problem,ValueType
does not imply it is numeric, nor that you can compare with>
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmpleTone
is an array of ints andTtwo
is an array of Monkeys
– Jamiec
Nov 21 '18 at 15:31
4
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
3
And also, you're checkingarray is ValueType
, which is alwaysfalse
, regardless of the type of elements contained in the array. The array itself is always a reference type.
– Rotem
Nov 21 '18 at 15:32
3
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
2
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58
|
show 8 more comments
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the <
operand.
public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Any idea on how to tackle this problem?
c#
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the <
operand.
public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Any idea on how to tackle this problem?
c#
c#
edited Nov 21 '18 at 16:10
Kevin Kouketsu
367214
367214
asked Nov 21 '18 at 15:29
Gil ShvarzmanGil Shvarzman
22
22
2
This is a common problem,ValueType
does not imply it is numeric, nor that you can compare with>
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmpleTone
is an array of ints andTtwo
is an array of Monkeys
– Jamiec
Nov 21 '18 at 15:31
4
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
3
And also, you're checkingarray is ValueType
, which is alwaysfalse
, regardless of the type of elements contained in the array. The array itself is always a reference type.
– Rotem
Nov 21 '18 at 15:32
3
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
2
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58
|
show 8 more comments
2
This is a common problem,ValueType
does not imply it is numeric, nor that you can compare with>
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmpleTone
is an array of ints andTtwo
is an array of Monkeys
– Jamiec
Nov 21 '18 at 15:31
4
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
3
And also, you're checkingarray is ValueType
, which is alwaysfalse
, regardless of the type of elements contained in the array. The array itself is always a reference type.
– Rotem
Nov 21 '18 at 15:32
3
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
2
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58
2
2
This is a common problem,
ValueType
does not imply it is numeric, nor that you can compare with >
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone
is an array of ints and Ttwo
is an array of Monkeys– Jamiec
Nov 21 '18 at 15:31
This is a common problem,
ValueType
does not imply it is numeric, nor that you can compare with >
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone
is an array of ints and Ttwo
is an array of Monkeys– Jamiec
Nov 21 '18 at 15:31
4
4
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
3
3
And also, you're checking
array is ValueType
, which is always false
, regardless of the type of elements contained in the array. The array itself is always a reference type.– Rotem
Nov 21 '18 at 15:32
And also, you're checking
array is ValueType
, which is always false
, regardless of the type of elements contained in the array. The array itself is always a reference type.– Rotem
Nov 21 '18 at 15:32
3
3
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
2
2
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58
|
show 8 more comments
3 Answers
3
active
oldest
votes
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T
as the output, not object
.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething
, and so on. A Func<A, B, C>
is a function that takes an A
, a B
, and returns a C
. Methods that do not manipulate an instance of their class are static
.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i
which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0
and < Length
of the array. Is there a way in the code I've written so far that this gets violated?
- Can you fix the bug and finish it off?
- Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parametersTOne
andTTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.
– Eric Lippert
Nov 21 '18 at 16:17
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must bepublic static T Merge<T>(T items1, T item2)
, and you can then make a constraint ofIComparable<T>
onT
to indicate that a T may be ordered with respect to another T.
– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
|
show 3 more comments
public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
add a comment |
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
1) You mention anIMergeable
interface but don't define it and don't use it in the code, instead using>
2) You checkarray is ValueType
which is alwaysfalse
.
– Rotem
Nov 21 '18 at 15:59
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415383%2fhow-do-i-use-if-else-in-a-generic-function-c-sharp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T
as the output, not object
.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething
, and so on. A Func<A, B, C>
is a function that takes an A
, a B
, and returns a C
. Methods that do not manipulate an instance of their class are static
.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i
which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0
and < Length
of the array. Is there a way in the code I've written so far that this gets violated?
- Can you fix the bug and finish it off?
- Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parametersTOne
andTTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.
– Eric Lippert
Nov 21 '18 at 16:17
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must bepublic static T Merge<T>(T items1, T item2)
, and you can then make a constraint ofIComparable<T>
onT
to indicate that a T may be ordered with respect to another T.
– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
|
show 3 more comments
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T
as the output, not object
.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething
, and so on. A Func<A, B, C>
is a function that takes an A
, a B
, and returns a C
. Methods that do not manipulate an instance of their class are static
.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i
which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0
and < Length
of the array. Is there a way in the code I've written so far that this gets violated?
- Can you fix the bug and finish it off?
- Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parametersTOne
andTTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.
– Eric Lippert
Nov 21 '18 at 16:17
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must bepublic static T Merge<T>(T items1, T item2)
, and you can then make a constraint ofIComparable<T>
onT
to indicate that a T may be ordered with respect to another T.
– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
|
show 3 more comments
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T
as the output, not object
.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething
, and so on. A Func<A, B, C>
is a function that takes an A
, a B
, and returns a C
. Methods that do not manipulate an instance of their class are static
.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i
which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0
and < Length
of the array. Is there a way in the code I've written so far that this gets violated?
- Can you fix the bug and finish it off?
- Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.
It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?
That is an unusual thing to do, but it is possible.
If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T
as the output, not object
.
The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.
If we have that then your method becomes:
public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{
Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething
, and so on. A Func<A, B, C>
is a function that takes an A
, a B
, and returns a C
. Methods that do not manipulate an instance of their class are static
.
Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:
object merged = new object[items1.Length + items2.Length];
Now your loop needs some work:
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.
Also, you have a counter i
which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?
Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:
int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{
There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0
and < Length
of the array. Is there a way in the code I've written so far that this gets violated?
- Can you fix the bug and finish it off?
- Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?
edited Nov 21 '18 at 16:05
answered Nov 21 '18 at 15:56
Eric LippertEric Lippert
545k14610671951
545k14610671951
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parametersTOne
andTTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.
– Eric Lippert
Nov 21 '18 at 16:17
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must bepublic static T Merge<T>(T items1, T item2)
, and you can then make a constraint ofIComparable<T>
onT
to indicate that a T may be ordered with respect to another T.
– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
|
show 3 more comments
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parametersTOne
andTTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.
– Eric Lippert
Nov 21 '18 at 16:17
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must bepublic static T Merge<T>(T items1, T item2)
, and you can then make a constraint ofIComparable<T>
onT
to indicate that a T may be ordered with respect to another T.
– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.
– Gil Shvarzman
Nov 21 '18 at 16:14
1
1
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters
TOne
and TTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.– Eric Lippert
Nov 21 '18 at 16:17
@GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters
TOne
and TTwo
? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.– Eric Lippert
Nov 21 '18 at 16:17
1
1
@GilShvarzman: If you want to merge two arrays of the same type then the signature must be
public static T Merge<T>(T items1, T item2)
, and you can then make a constraint of IComparable<T>
on T
to indicate that a T may be ordered with respect to another T.– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: If you want to merge two arrays of the same type then the signature must be
public static T Merge<T>(T items1, T item2)
, and you can then make a constraint of IComparable<T>
on T
to indicate that a T may be ordered with respect to another T.– Eric Lippert
Nov 21 '18 at 16:19
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
@GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.
– Eric Lippert
Nov 21 '18 at 16:20
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :
– Gil Shvarzman
Nov 21 '18 at 16:22
|
show 3 more comments
public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
add a comment |
public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
add a comment |
public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)
}
}
return mergedArray;
}
answered Nov 21 '18 at 15:37
themadmaxthemadmax
1,3541624
1,3541624
add a comment |
add a comment |
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
1) You mention anIMergeable
interface but don't define it and don't use it in the code, instead using>
2) You checkarray is ValueType
which is alwaysfalse
.
– Rotem
Nov 21 '18 at 15:59
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
add a comment |
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
1) You mention anIMergeable
interface but don't define it and don't use it in the code, instead using>
2) You checkarray is ValueType
which is alwaysfalse
.
– Rotem
Nov 21 '18 at 15:59
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
add a comment |
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.
Something like a "IMergable" interface that you have to write yourself.
public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
where Tone : IMergeable, Ttwo : IMergeable
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
Alternatively, you could jsut use one type:
public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
{
IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])
}
}
}
answered Nov 21 '18 at 15:42
ChristopherChristopher
2,9962824
2,9962824
1) You mention anIMergeable
interface but don't define it and don't use it in the code, instead using>
2) You checkarray is ValueType
which is alwaysfalse
.
– Rotem
Nov 21 '18 at 15:59
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
add a comment |
1) You mention anIMergeable
interface but don't define it and don't use it in the code, instead using>
2) You checkarray is ValueType
which is alwaysfalse
.
– Rotem
Nov 21 '18 at 15:59
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
1) You mention an
IMergeable
interface but don't define it and don't use it in the code, instead using >
2) You check array is ValueType
which is always false
.– Rotem
Nov 21 '18 at 15:59
1) You mention an
IMergeable
interface but don't define it and don't use it in the code, instead using >
2) You check array is ValueType
which is always false
.– Rotem
Nov 21 '18 at 15:59
2
2
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.
– Rotem
Nov 21 '18 at 16:04
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415383%2fhow-do-i-use-if-else-in-a-generic-function-c-sharp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
This is a common problem,
ValueType
does not imply it is numeric, nor that you can compare with>
. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmpleTone
is an array of ints andTtwo
is an array of Monkeys– Jamiec
Nov 21 '18 at 15:31
4
You want to compare two different types
– miechooy
Nov 21 '18 at 15:31
3
And also, you're checking
array is ValueType
, which is alwaysfalse
, regardless of the type of elements contained in the array. The array itself is always a reference type.– Rotem
Nov 21 '18 at 15:32
3
You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.
– Eric Lippert
Nov 21 '18 at 15:56
2
If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.
– Eric Lippert
Nov 21 '18 at 15:58