Composing a common interface with c# library class
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
Suppose I have a class:
public class Foo<TKey, TValue> {
private readonly ConcurrentDictionary<TKey, TValue> m_dict;
public Foo() {
m_dict = new ConcurrentDictionary<TKey, TValue>();
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This is the API for ConcurrentDictionary : https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2?view=netframework-4.7.2
It implements the following interfaces:
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>
Essentially my class Foo uses a subset of ConcurrentDictionary's API methods.
Now there is a requirement to use a ConcurrentTreeMap<TKey, TValue>
in the client class in certain use cases. I have implemented a ConcurrentTreeMap<TKey, TValue>
class myself with all the API methods the client class is requiring. This class implements IDictionary<TKey, TValue>
and ICollection<KeyValuePair<TKey, TValue>>
I want my Foo client class to be able to use both ConcurrentDictionary and ConcurrentTreeMap. Something like this, simplified:
public class Foo<TKey, TValue> {
private readonly IConcurrentDictionary<TKey, TValue> m_dict;
public Foo(IConcurrentDictionary dict) {
m_dict = dict;
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This would be easy for languages like Python and Go. If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two. Or I could define a composite interface of all the interfaces ConcurrentDictionary implements. But since ConcurrentDictionary is part of some base c# library, I can't do that. Should I use some type of proxy class between ConcurrentDictionary and my custom interface? That seems like a lot of boilerplate code I'd have to write.
The backing data between a treemap and a hashmap(dictionary) is quite different so I also couldn't inherit ConcurrentTreeMap from ConcurrentDictionary (most of its methods are not virtual, anyways).
c# oop design-patterns dependency-injection interface
add a comment |
Suppose I have a class:
public class Foo<TKey, TValue> {
private readonly ConcurrentDictionary<TKey, TValue> m_dict;
public Foo() {
m_dict = new ConcurrentDictionary<TKey, TValue>();
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This is the API for ConcurrentDictionary : https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2?view=netframework-4.7.2
It implements the following interfaces:
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>
Essentially my class Foo uses a subset of ConcurrentDictionary's API methods.
Now there is a requirement to use a ConcurrentTreeMap<TKey, TValue>
in the client class in certain use cases. I have implemented a ConcurrentTreeMap<TKey, TValue>
class myself with all the API methods the client class is requiring. This class implements IDictionary<TKey, TValue>
and ICollection<KeyValuePair<TKey, TValue>>
I want my Foo client class to be able to use both ConcurrentDictionary and ConcurrentTreeMap. Something like this, simplified:
public class Foo<TKey, TValue> {
private readonly IConcurrentDictionary<TKey, TValue> m_dict;
public Foo(IConcurrentDictionary dict) {
m_dict = dict;
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This would be easy for languages like Python and Go. If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two. Or I could define a composite interface of all the interfaces ConcurrentDictionary implements. But since ConcurrentDictionary is part of some base c# library, I can't do that. Should I use some type of proxy class between ConcurrentDictionary and my custom interface? That seems like a lot of boilerplate code I'd have to write.
The backing data between a treemap and a hashmap(dictionary) is quite different so I also couldn't inherit ConcurrentTreeMap from ConcurrentDictionary (most of its methods are not virtual, anyways).
c# oop design-patterns dependency-injection interface
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34
add a comment |
Suppose I have a class:
public class Foo<TKey, TValue> {
private readonly ConcurrentDictionary<TKey, TValue> m_dict;
public Foo() {
m_dict = new ConcurrentDictionary<TKey, TValue>();
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This is the API for ConcurrentDictionary : https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2?view=netframework-4.7.2
It implements the following interfaces:
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>
Essentially my class Foo uses a subset of ConcurrentDictionary's API methods.
Now there is a requirement to use a ConcurrentTreeMap<TKey, TValue>
in the client class in certain use cases. I have implemented a ConcurrentTreeMap<TKey, TValue>
class myself with all the API methods the client class is requiring. This class implements IDictionary<TKey, TValue>
and ICollection<KeyValuePair<TKey, TValue>>
I want my Foo client class to be able to use both ConcurrentDictionary and ConcurrentTreeMap. Something like this, simplified:
public class Foo<TKey, TValue> {
private readonly IConcurrentDictionary<TKey, TValue> m_dict;
public Foo(IConcurrentDictionary dict) {
m_dict = dict;
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This would be easy for languages like Python and Go. If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two. Or I could define a composite interface of all the interfaces ConcurrentDictionary implements. But since ConcurrentDictionary is part of some base c# library, I can't do that. Should I use some type of proxy class between ConcurrentDictionary and my custom interface? That seems like a lot of boilerplate code I'd have to write.
The backing data between a treemap and a hashmap(dictionary) is quite different so I also couldn't inherit ConcurrentTreeMap from ConcurrentDictionary (most of its methods are not virtual, anyways).
c# oop design-patterns dependency-injection interface
Suppose I have a class:
public class Foo<TKey, TValue> {
private readonly ConcurrentDictionary<TKey, TValue> m_dict;
public Foo() {
m_dict = new ConcurrentDictionary<TKey, TValue>();
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This is the API for ConcurrentDictionary : https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2?view=netframework-4.7.2
It implements the following interfaces:
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>
Essentially my class Foo uses a subset of ConcurrentDictionary's API methods.
Now there is a requirement to use a ConcurrentTreeMap<TKey, TValue>
in the client class in certain use cases. I have implemented a ConcurrentTreeMap<TKey, TValue>
class myself with all the API methods the client class is requiring. This class implements IDictionary<TKey, TValue>
and ICollection<KeyValuePair<TKey, TValue>>
I want my Foo client class to be able to use both ConcurrentDictionary and ConcurrentTreeMap. Something like this, simplified:
public class Foo<TKey, TValue> {
private readonly IConcurrentDictionary<TKey, TValue> m_dict;
public Foo(IConcurrentDictionary dict) {
m_dict = dict;
}
public void AddThings(TKey key, TValue val) {
m_dict.Add(key, val);
}
public void RemoveThings(TKey key) {
m_dict.Remove(key);
}
//}
This would be easy for languages like Python and Go. If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two. Or I could define a composite interface of all the interfaces ConcurrentDictionary implements. But since ConcurrentDictionary is part of some base c# library, I can't do that. Should I use some type of proxy class between ConcurrentDictionary and my custom interface? That seems like a lot of boilerplate code I'd have to write.
The backing data between a treemap and a hashmap(dictionary) is quite different so I also couldn't inherit ConcurrentTreeMap from ConcurrentDictionary (most of its methods are not virtual, anyways).
c# oop design-patterns dependency-injection interface
c# oop design-patterns dependency-injection interface
asked Nov 29 '18 at 1:29
user3805884user3805884
507
507
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34
add a comment |
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34
add a comment |
1 Answer
1
active
oldest
votes
Foo<TKey, TValue>
is essentially a wrapper around a collection. If you want a wrapper around a different collection, then possibly the best approach would be to create an interface:
public interface IFoo<TKey, TValue>
{
void AddThings(TKey key, TValue val);
void RemoveThings(TKey key);
}
...and have two separate implementations of it - one using an inner ConcurrentDictionary
and the other using your ConcurrentTreeMap<TKey, TValue>
.
Here's one implementation - I don't know the other because I don't have your ConcurrentTree
class:
public class ConcurrentDictionaryFoo : IFoo<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, TValue> _dictionary
= new ConcurrentDictionary<TKey, TValue>();
void AddThings(TKey key, TValue val)
{
_dictionary.TryAdd(key, val);
}
void RemoveThings(TKey key)
{
_dictionary.TryRemove(key);
}
}
That's the most common practice when we have one interface and multiple implementations. We wouldn't normally try to put both implementations in one class.
You could put them both in one class. You could have both a ConcurrentDictionary
and a ConcurrentTreeMap
within one class, and then maybe some flag in the constructor would tell the class which inner collection it should use.
But if we follow where that leads, what happens if you need another implementation that uses a different collection, and another, and another? That's an easy problem to solve if you're creating distinct implementations of IFoo
, but it would be complex and messy if you tried to put all possible implementations in a single class.
What if this class is complex and the collection is just one small part of it, and you don't want to duplicate the rest of the code just because you want it to work with either collection type?
In that case you would still create an interface to represent the collection, and have separate implementations for ConcurrentDictionary
and ConcurrentTreeMap
. Then Foo
would depend on that abstraction, and not on either concrete collection. Something like this:
public class Foo<TKey, TValue>
{
private readonly IFooDictionary<TKey, TValue> _dictionary;
public Foo(IFooDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
Now Foo
just depends on IFooDictionary
and doesn't know if the underlying implementation is a ConcurrentDictionary
or a ConcurrentTreeMap
.
This somewhat lines up with what you said:
If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two.
Except that common interface isn't something you extract - it's something you create. You define the interface that describes what your other classes need to use this thing for. Then you just create an adapter or wrapper around the ConcurrentDictionary
or ConcurrentTreeMap
which directs the methods of the interface to the correct methods of the inner collection - just like in the example above where the AddThings
method calls the TryAdd
method of the inner dictionary.
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
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%2f53530570%2fcomposing-a-common-interface-with-c-sharp-library-class%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Foo<TKey, TValue>
is essentially a wrapper around a collection. If you want a wrapper around a different collection, then possibly the best approach would be to create an interface:
public interface IFoo<TKey, TValue>
{
void AddThings(TKey key, TValue val);
void RemoveThings(TKey key);
}
...and have two separate implementations of it - one using an inner ConcurrentDictionary
and the other using your ConcurrentTreeMap<TKey, TValue>
.
Here's one implementation - I don't know the other because I don't have your ConcurrentTree
class:
public class ConcurrentDictionaryFoo : IFoo<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, TValue> _dictionary
= new ConcurrentDictionary<TKey, TValue>();
void AddThings(TKey key, TValue val)
{
_dictionary.TryAdd(key, val);
}
void RemoveThings(TKey key)
{
_dictionary.TryRemove(key);
}
}
That's the most common practice when we have one interface and multiple implementations. We wouldn't normally try to put both implementations in one class.
You could put them both in one class. You could have both a ConcurrentDictionary
and a ConcurrentTreeMap
within one class, and then maybe some flag in the constructor would tell the class which inner collection it should use.
But if we follow where that leads, what happens if you need another implementation that uses a different collection, and another, and another? That's an easy problem to solve if you're creating distinct implementations of IFoo
, but it would be complex and messy if you tried to put all possible implementations in a single class.
What if this class is complex and the collection is just one small part of it, and you don't want to duplicate the rest of the code just because you want it to work with either collection type?
In that case you would still create an interface to represent the collection, and have separate implementations for ConcurrentDictionary
and ConcurrentTreeMap
. Then Foo
would depend on that abstraction, and not on either concrete collection. Something like this:
public class Foo<TKey, TValue>
{
private readonly IFooDictionary<TKey, TValue> _dictionary;
public Foo(IFooDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
Now Foo
just depends on IFooDictionary
and doesn't know if the underlying implementation is a ConcurrentDictionary
or a ConcurrentTreeMap
.
This somewhat lines up with what you said:
If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two.
Except that common interface isn't something you extract - it's something you create. You define the interface that describes what your other classes need to use this thing for. Then you just create an adapter or wrapper around the ConcurrentDictionary
or ConcurrentTreeMap
which directs the methods of the interface to the correct methods of the inner collection - just like in the example above where the AddThings
method calls the TryAdd
method of the inner dictionary.
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
add a comment |
Foo<TKey, TValue>
is essentially a wrapper around a collection. If you want a wrapper around a different collection, then possibly the best approach would be to create an interface:
public interface IFoo<TKey, TValue>
{
void AddThings(TKey key, TValue val);
void RemoveThings(TKey key);
}
...and have two separate implementations of it - one using an inner ConcurrentDictionary
and the other using your ConcurrentTreeMap<TKey, TValue>
.
Here's one implementation - I don't know the other because I don't have your ConcurrentTree
class:
public class ConcurrentDictionaryFoo : IFoo<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, TValue> _dictionary
= new ConcurrentDictionary<TKey, TValue>();
void AddThings(TKey key, TValue val)
{
_dictionary.TryAdd(key, val);
}
void RemoveThings(TKey key)
{
_dictionary.TryRemove(key);
}
}
That's the most common practice when we have one interface and multiple implementations. We wouldn't normally try to put both implementations in one class.
You could put them both in one class. You could have both a ConcurrentDictionary
and a ConcurrentTreeMap
within one class, and then maybe some flag in the constructor would tell the class which inner collection it should use.
But if we follow where that leads, what happens if you need another implementation that uses a different collection, and another, and another? That's an easy problem to solve if you're creating distinct implementations of IFoo
, but it would be complex and messy if you tried to put all possible implementations in a single class.
What if this class is complex and the collection is just one small part of it, and you don't want to duplicate the rest of the code just because you want it to work with either collection type?
In that case you would still create an interface to represent the collection, and have separate implementations for ConcurrentDictionary
and ConcurrentTreeMap
. Then Foo
would depend on that abstraction, and not on either concrete collection. Something like this:
public class Foo<TKey, TValue>
{
private readonly IFooDictionary<TKey, TValue> _dictionary;
public Foo(IFooDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
Now Foo
just depends on IFooDictionary
and doesn't know if the underlying implementation is a ConcurrentDictionary
or a ConcurrentTreeMap
.
This somewhat lines up with what you said:
If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two.
Except that common interface isn't something you extract - it's something you create. You define the interface that describes what your other classes need to use this thing for. Then you just create an adapter or wrapper around the ConcurrentDictionary
or ConcurrentTreeMap
which directs the methods of the interface to the correct methods of the inner collection - just like in the example above where the AddThings
method calls the TryAdd
method of the inner dictionary.
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
add a comment |
Foo<TKey, TValue>
is essentially a wrapper around a collection. If you want a wrapper around a different collection, then possibly the best approach would be to create an interface:
public interface IFoo<TKey, TValue>
{
void AddThings(TKey key, TValue val);
void RemoveThings(TKey key);
}
...and have two separate implementations of it - one using an inner ConcurrentDictionary
and the other using your ConcurrentTreeMap<TKey, TValue>
.
Here's one implementation - I don't know the other because I don't have your ConcurrentTree
class:
public class ConcurrentDictionaryFoo : IFoo<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, TValue> _dictionary
= new ConcurrentDictionary<TKey, TValue>();
void AddThings(TKey key, TValue val)
{
_dictionary.TryAdd(key, val);
}
void RemoveThings(TKey key)
{
_dictionary.TryRemove(key);
}
}
That's the most common practice when we have one interface and multiple implementations. We wouldn't normally try to put both implementations in one class.
You could put them both in one class. You could have both a ConcurrentDictionary
and a ConcurrentTreeMap
within one class, and then maybe some flag in the constructor would tell the class which inner collection it should use.
But if we follow where that leads, what happens if you need another implementation that uses a different collection, and another, and another? That's an easy problem to solve if you're creating distinct implementations of IFoo
, but it would be complex and messy if you tried to put all possible implementations in a single class.
What if this class is complex and the collection is just one small part of it, and you don't want to duplicate the rest of the code just because you want it to work with either collection type?
In that case you would still create an interface to represent the collection, and have separate implementations for ConcurrentDictionary
and ConcurrentTreeMap
. Then Foo
would depend on that abstraction, and not on either concrete collection. Something like this:
public class Foo<TKey, TValue>
{
private readonly IFooDictionary<TKey, TValue> _dictionary;
public Foo(IFooDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
Now Foo
just depends on IFooDictionary
and doesn't know if the underlying implementation is a ConcurrentDictionary
or a ConcurrentTreeMap
.
This somewhat lines up with what you said:
If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two.
Except that common interface isn't something you extract - it's something you create. You define the interface that describes what your other classes need to use this thing for. Then you just create an adapter or wrapper around the ConcurrentDictionary
or ConcurrentTreeMap
which directs the methods of the interface to the correct methods of the inner collection - just like in the example above where the AddThings
method calls the TryAdd
method of the inner dictionary.
Foo<TKey, TValue>
is essentially a wrapper around a collection. If you want a wrapper around a different collection, then possibly the best approach would be to create an interface:
public interface IFoo<TKey, TValue>
{
void AddThings(TKey key, TValue val);
void RemoveThings(TKey key);
}
...and have two separate implementations of it - one using an inner ConcurrentDictionary
and the other using your ConcurrentTreeMap<TKey, TValue>
.
Here's one implementation - I don't know the other because I don't have your ConcurrentTree
class:
public class ConcurrentDictionaryFoo : IFoo<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, TValue> _dictionary
= new ConcurrentDictionary<TKey, TValue>();
void AddThings(TKey key, TValue val)
{
_dictionary.TryAdd(key, val);
}
void RemoveThings(TKey key)
{
_dictionary.TryRemove(key);
}
}
That's the most common practice when we have one interface and multiple implementations. We wouldn't normally try to put both implementations in one class.
You could put them both in one class. You could have both a ConcurrentDictionary
and a ConcurrentTreeMap
within one class, and then maybe some flag in the constructor would tell the class which inner collection it should use.
But if we follow where that leads, what happens if you need another implementation that uses a different collection, and another, and another? That's an easy problem to solve if you're creating distinct implementations of IFoo
, but it would be complex and messy if you tried to put all possible implementations in a single class.
What if this class is complex and the collection is just one small part of it, and you don't want to duplicate the rest of the code just because you want it to work with either collection type?
In that case you would still create an interface to represent the collection, and have separate implementations for ConcurrentDictionary
and ConcurrentTreeMap
. Then Foo
would depend on that abstraction, and not on either concrete collection. Something like this:
public class Foo<TKey, TValue>
{
private readonly IFooDictionary<TKey, TValue> _dictionary;
public Foo(IFooDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
Now Foo
just depends on IFooDictionary
and doesn't know if the underlying implementation is a ConcurrentDictionary
or a ConcurrentTreeMap
.
This somewhat lines up with what you said:
If I had access to ConcurrentDictionary's implementation I would obviously just extract a common interface type between the two.
Except that common interface isn't something you extract - it's something you create. You define the interface that describes what your other classes need to use this thing for. Then you just create an adapter or wrapper around the ConcurrentDictionary
or ConcurrentTreeMap
which directs the methods of the interface to the correct methods of the inner collection - just like in the example above where the AddThings
method calls the TryAdd
method of the inner dictionary.
edited Nov 29 '18 at 2:23
answered Nov 29 '18 at 1:56
Scott HannenScott Hannen
13.3k1426
13.3k1426
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
add a comment |
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
right, this is similar to the facade or wrapper
– Chris Hayes
Nov 29 '18 at 5:45
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%2f53530570%2fcomposing-a-common-interface-with-c-sharp-library-class%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
Im guessing you want thread safety here, just be very careful with this type of thing, you could easily get the thread safety aspect wrong
– Michael Randall
Nov 29 '18 at 1:34